LC3 Decoding: SNS Decoder

 

LC3 Decoding: SNS Decoder
Chapter 3, Section 3.4.7 — Scale Factor Decoding, MPVQ De-enumeration, Interpolation, Spectral Shaping
Chapter
3 — Section 3.4.7
Subsections
3.4.7.1 to 3.4.7.4
Level
Advanced

The SNS decoder reconstructs the 16 quantized scale factors from the bitstream, interpolates them back to 64 per-band values, and then applies the inverse spectral shaping — multiplying the spectrum by the scale factors (instead of dividing as the encoder did). This restores the original spectral shape before the signal is transformed back to time domain.

Keywords

SNS Scale Factor Decoding MPVQ De-enumeration MPVQdeenum IDCT Synthesis gSNS Inverse Spectral Shaping

3.4.7.1 SNS Decoder Overview

The SNS decoder performs three steps in order:

Step Action Section
1 Decode 16 quantized scale factors scfQ(n) from bitstream (Stage 1 + Stage 2 VQ inverse) 3.4.7.2
2 Interpolate 16 scfQ values to 64 per-band values scfQint 3.4.7.3
3 Apply inverse spectral shaping: multiply X̂s(k) by gSNS(b) to get X̂(k) 3.4.7.4

The quantized scale factors are identical to those computed by the encoder — there is no additional error beyond what the encoder’s two-stage VQ introduces.

3.4.7.2.1 Stage 1 SNS VQ Decoding

Stage 1 reads ind_LF (5 bits) and ind_HF (5 bits) from the bitstream and reconstructs the first-stage vector st1 from the LFCB and HFCB codebook tables:

ind_LF = read_uint(bytes, &bp_side, &mask_side, 5)
ind_HF = read_uint(bytes, &bp_side, &mask_side, 5)
st1(n) = LFCB[ind_LF][n], for n = 0..7
st1(n+8) = HFCB[ind_HF][n], for n = 0..7

3.4.7.2.2 Stage 2 SNS VQ Decoding

Stage 2 reads the jointly encoded shape and gain bits from the bitstream. The reading and demultiplexing is the exact reverse of the encoder’s multiplexing:

submodeMSB = read_bit(…) /* shape_j >> 1 */ Gind = read_uint(…, 1 or 2) /* gain MSBs (1 bit if submodeMSB=0, 2 bits if =1) */ LS_indA = read_bit(…) /* leading sign of shape set A */ /* Read 25 bits as joint index (13 bits + 12 bits) or 24 bits (12+12) */

The joint index is then split using the dec_split_st2VQ_CW function into submodeLSB, idxA, and (for regular shapes) LS_indB and idxB. The final shape_j and gain_i are recovered:

shape_j = (submodeMSB << 1) + submodeLSB
gain_i = Gind (full index after any LSB merging)

The dec_split_st2VQ_CW function handles the four submode cases (regular, regular_lf, outlier_near, outlier_far) and sets BEC_detect if the received joint index is out of the valid range for the decoded submode.

3.4.7.2.2.1 MPVQ De-enumeration

MPVQ de-enumeration converts the (LS_ind, MPVQ_ind) pair back to a signed integer PVQ pulse train vector y. This is the inverse of the MPVQ enumeration done by the encoder.

The algorithm uses the MPVQ_offsets table from Section 3.7.3.2. Starting from position 0 and walking forward to dim_in−1, it determines how many pulses are at each position using table lookups:

/* MPVQdeenum: convert (LS_ind, MPVQ_ind) → signed integer PVQ vector y */
/* Simplified flow: */
leading_sign = (LS_ind != 0) ? −1 : +1;
for pos = 0 to dim_in−1:
    if ind != 0:
        /* Find how many pulses go at this position using MPVQ_offsets */
        k_acc = k_max_local
        while ind < MPVQ_offsets[dim_in−1−pos][k_acc]: k_acc--
        /* Set vec_out[pos] based on k_delta and leading_sign */
        /* Update leading_sign from the next bits of ind */
        k_max_local -= k_delta
    else:
        vec_out[pos] = leading_sign × k_max_local
        break

The de-enumeration calls for each shape are in Table 3.21. For shape_j=0, two separate calls are made: MPVQdeenum(10,10,LS_indA,idxA,y0) for set A positions, and MPVQdeenum(6,1,LS_indB,idxB,z) for set B positions.

3.4.7.2.3 and 3.4.7.2.4 — Normalization and Scale Factor Synthesis

Unit energy normalization: The de-enumerated integer vector y_shape_j is normalized to unit energy over 16 dimensions: xq = y / sqrt(yT × y).

Scale factor synthesis: The adjustment gain G for (gain_i, shape_j) is looked up from Table 3.11. Then the quantized scale factor vector is reconstructed using the IDCT rotation (D^T matrix from Section 3.7.3.2):

scfQ(n) = st1(n) + G_gain_i_shape_j × SUM[col=0..15] xq_shape_j(col) × D(col + n×16)
for n = 0..15

This is identical to Equation 62 used by the encoder to synthesize the quantized scale factors from Stage 1 and Stage 2 components.

3.4.7.3 Scale Factor Interpolation

The 16 scfQ values are interpolated to 64 values using the same formula as the encoder (Equation 123 = identical to Equation 63 at the encoder). The NB < 64 reduction and linear domain conversion are also identical:

gSNS(b) = 2^(+scfQint(b)), for b = 0..NB−1

Note the critical sign difference from the encoder: here the sign is positive (multiplication = amplifying). At the encoder, the sign was negative (division = attenuating). The SNS encoder attenuates the spectrum by gSNS; the decoder amplifies it back.

3.4.7.4 Inverse Spectral Shaping

The interpolated decoder-side scale factors gSNS(b) are applied to the TNS-decoded spectrum X̂s(k) to produce the final reconstructed spectrum X̂(k):

for (b = 0; b < Nb; b++) {
    for (k = Ifs(b); k < Ifs(b+1); k++) {
        Xh[k] = Xsh[k] * gSNS(b);   /* multiply (decoder) vs divide (encoder) */
    }
}

The output X̂(k) is the fully reconstructed spectral representation. It is now passed to the inverse LD-MDCT (Section 3.4.8) to convert back to the time domain.

Next in this Series

Sections 3.4.8–3.4.10 — Inverse LD-MDCT synthesis, LTPF decoder, and output signal scaling

Next Tutorial → All Tutorials

Leave a Reply

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