LC3 General Codec Parameters

 

LC3 General Codec Parameters
Chapter 3, Section 3.2 — Audio Channels, Sampling Rates, Bits per Sample, Frame Size, Bit Budget
Chapter
3 — Section 3.2
Subsections
3.2.1 to 3.2.5
Level
Intermediate

This tutorial explains the core parameters that govern how the LC3 codec operates: the supported sampling rates, how bit depth is handled, how frame size is calculated from those parameters, and how the bit budget for a frame is computed. These parameters are the foundation for all encoding and decoding decisions.

Keywords

Sampling Rate Index fsind fscal Frame Size NF MDCT Zeros Z nbytes Bitrate

3.2.1 Audio Channels

LC3 processes one audio channel at a time. The entire specification describes a single-channel codec. Stereo or multi-channel audio is handled by running multiple independent mono LC3 encoders/decoders in parallel — one per channel. There is no cross-channel coding or joint stereo in LC3 itself. The number of channels (Nc) and any channel relationship is defined by the Bluetooth audio profile above.

3.2.2 Sampling Rates

LC3 supports six sampling rates. For 44.1 kHz, the codec uses the same frame configuration as 48 kHz — this avoids implementing a separate code path. The slightly longer actual frame duration at 44.1 kHz is absorbed by the fscal factor.

A sampling rate index (fsind) is computed to look up parameters from tables throughout the spec:

fsind = min(4, fs/8000 − 1)
fs (Hz) fsind fscal Application
8,000 0 1 NB telephony, hearing aids
16,000 1 1 HA-SQ speech quality
24,000 2 1 HA-HQ, SSWB audio
32,000 3 1 SWB, broadcast quality
44,100 4 48000/44100 ≈ 1.0884 CD/music, uses 48k frame config
48,000 4 1 FB audio, highest quality

Note: 44.1 kHz and 48 kHz share the same fsind = 4. The fscal factor is the only difference between the two.

3.2.3 Bits per Sample

The LC3 algorithm is designed to work with input PCM samples in the range:

  • Minimum bit depth: 16 bits per sample
  • Maximum bit depth: 32 bits per sample
  • Typical values: 16, 24, or 32 bits

The encoder’s input bit depth (bits_per_audio_sample_enc) and the decoder’s output bit depth (bits_per_audio_sample_dec) can be different. For example, a 24-bit encoded stream can be decoded to 16-bit output. The scaling is applied at the encoder’s input stage (Section 3.3.3) and at the decoder’s output stage (Section 3.4.10).

3.2.4 Frame Size and Delay

The frame size in samples is calculated directly from the sampling rate and frame duration:

NF = (fs × fscal × Nms) / 1000

For 48 kHz, 10 ms: NF = (48000 × 1 × 10) / 1000 = 480 samples. For 44.1 kHz, 10 ms: NF = (44100 × 1.0884 × 10) / 1000 = 480 samples (same).

The algorithmic delay D is:

D = 1000 × (2 × NF − 2 × Z) / fs

Where Z (leading zeros in the MDCT window) is:

Frame Duration (Nms) Z (leading zeros) Delay D
7.5 ms 7NF / 30 11.5 ms (8–48 kHz) / ~12.5 ms (44.1 kHz)
10 ms 3NF / 8 12.5 ms (8–48 kHz) / ~13.6 ms (44.1 kHz)

The delay is entirely from the MDCT look-ahead (the Z leading zeros in the window). There is no extra processing delay beyond what the transform itself introduces.

3.2.5 Bit Budget and Bitrate

The encoder receives nbytes (the byte_count) as an external input for each frame. This defines the total bit budget for everything: side information, SNS, TNS, LTPF, global gain, and the spectral coefficients themselves.

Key relationships:

nbits = 8 × nbytes
bitrate = ⌈ 8000 × nbytes / (Nms × fscal) ⌉ (in bps)

To convert a target bitrate (in bps) to nbytes for session setup:

nbytes = ⌊ bitrate × Nms × fscal / 8000 ⌋

The result is floored (rounded down) so that nbytes is always an integer. The codec works on byte boundaries — nbytes is always an integer between 20 and 400.

Frame Mode Min nbytes Max nbytes Bitrate Range
10 ms 20 400 16,000 – 320,000 bps
7.5 ms 20 400 21,334 – 426,667 bps
10 ms at 44.1 kHz 20 400 14,700 – 294,000 bps
7.5 ms at 44.1 kHz 20 400 19,600 – 392,000 bps

The spec only guarantees verified algorithm behavior in the 20–400 bytes range. Using nbytes outside this range is not supported.

Parameters in BlueZ BAP Configuration

In BlueZ, when you configure an LC3 codec via the BAP (Basic Audio Profile), the parameters from Section 3.2 appear directly in the Codec_Specific_Configuration LTV structure. Here is how they map:

/* Convert desired bitrate to nbytes (LC3 spec Section 3.2.5 formula) */
/* For 48 kHz, 10ms frame at 80 kbps:                                  */
double bitrate = 80000.0;          /* bits per second */
double Nms     = 10.0;             /* frame duration ms */
double fscal   = 1.0;             /* 1.0 for all rates except 44.1 kHz */
int nbytes = (int)floor(bitrate * Nms * fscal / 8000.0);
/* nbytes = floor(80000 * 10 * 1 / 8000) = floor(100) = 100 bytes */

/* Frame size NF for 48 kHz, 10ms */
int fs   = 48000;
int NF   = (int)(fs * fscal * Nms / 1000.0);  /* = 480 samples */

/* Leading zeros Z for 10 ms frame */
int Z = (3 * NF) / 8;   /* = 180 for NF=480 */

/* Algorithmic delay D in ms */
double D = 1000.0 * (2 * NF - 2 * Z) / (double)fs;
/* D = 1000 * (960 - 360) / 48000 = 1000 * 600 / 48000 = 12.5 ms */

/* These values map to BlueZ ISO QoS:                               */
/* qos.ucast.sdu = nbytes = 100 bytes for this example              */
printf("nbytes=%d NF=%d Z=%d delay=%.1fms\n", nbytes, NF, Z, D);
/* Output: nbytes=100 NF=480 Z=180 delay=12.5ms                    */

Next in this Series

Section 3.3 Encoding Part 1 — Encoder module pipeline, input signal, input scaling, and LD-MDCT analysis

Next Tutorial → All Tutorials

Leave a Reply

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