Subchannels

Every CD sector carries, alongside its 2352 bytes of main data, 96 bytes of subchannel data. This page explains where those bytes come from, what each of the eight subchannels is for, how the important Q subchannel is structured, and how image files lay the 96 bytes out. The layouts are not compatible: MDF interleaves the eight channels and CloneCD's .sub stores them one after another.

DVDs have no subchannel. Everything here applies to CDs only.


1. Where subchannel data comes from #

As described in On-disk encoding, a CD sector is made of 98 small frames, and each one contains one subcode byte next to its 32 bytes of main data and parity. Collected over the sector, that gives 98 subcode bytes:

  • bytes 0 and 1 are the sync patterns S0 and S1. They are special EFM symbols, not data, and they mark the start of the block;
  • bytes 2–97 are 96 data bytes.

Each of those 96 bytes contains one bit from each of eight subchannels, named after the bit positions:

bit:        7   6   5   4   3   2   1   0
subchannel: P   Q   R   S   T   U   V   W

So each subchannel gets 96 bits (12 bytes) per sector, and there are 8 × 12 = 96 bytes in total. At 75 sectors per second each subchannel runs at 7,200 bit/s, and all of them together at 57,600 bit/s.

Important properties:

  • The subchannel is not protected by CIRC and has no sector-level EDC/ECC. Errors in it are common when reading. The Q channel has its own CRC (section 4.4) so a reader can at least detect bad Q data. CD-TEXT and CD+G add their own protection in R–W.
  • The subchannel is not interleaved like the main data, so its alignment relative to the main data depends on the drive (see encoding §2.2).
  • It runs everywhere: in the lead-in, every pregap, every track and the lead-out. In the lead-in, the Q channel is the only place the Table of Contents exists.

2. P: the pause flag #

P is the simplest channel. All 96 bits of a sector are normally the same value:

  • P = 1 during the pause before a track (its pregap, index 0) and at the start of the disc. It tells simple players "a new track starts here". Players of the early 1980s used it to find track boundaries without decoding Q.
  • P = 0 while a track plays.
  • In the lead-out, P alternates between 0 and 1 at about 2 Hz, so a player can recognise the end of the disc.

Modern drives ignore P and use Q. Images that store subchannel still keep P, and some copy protections (rarely) check it.


3. R–W: CD+G, CD-TEXT and others #

The six channels R, S, T, U, V and W are usually treated together, as 6-bit symbols (one bit from each of R–W per subcode byte). They are empty (all zero) on most discs. When used, they carry:

3.1 CD+G (CD+Graphics) and CD+EG #

Karaoke discs use R–W in the program area for low-resolution graphics (300 × 216 pixels, 16 colours) drawn in sync with the music. The 96 symbols of a sector form 4 packs of 24 symbols. Each pack holds a command (such as "tile block", "fill", "scroll" or "load colour table") with its own Reed–Solomon protection. CD+G tracks are the reason CUE sheets have a CDG track type (2448 bytes per sector: audio + raw subchannel).

3.2 CD-TEXT #

CD-TEXT puts album and track titles, performers, songwriters and so on onto an audio CD. It lives in the R–W channels of the lead-in, where it is repeated continuously. (A variant in the program area exists in the spec but is very rarely used.)

CD-TEXT is a sequence of 18-byte packs:

byte 0       Pack type (ID1):
               0x80 TITLE        0x81 PERFORMER   0x82 SONGWRITER   0x83 COMPOSER
               0x84 ARRANGER     0x85 MESSAGE     0x86 DISC_ID      0x87 GENRE
               0x88 TOC info     0x89 TOC info 2  0x8D closed info  0x8E UPC/EAN & ISRC
               0x8F size info (block summary: character set, language, pack counts)
byte 1       Track number (ID2): 0 = whole disc, 1–99 = track. Bit 7 = extension flag.
byte 2       Sequence number (ID3): running pack counter, 0–255
byte 3       Block number and character position (ID4):
               bit 7 = double-byte characters (e.g. Japanese MS-JIS),
               bits 6–4 = block number (0–7; one block per language),
               bits 3–0 = position within the current string at which this pack's text starts
bytes 4–15   12 bytes of text payload (NUL-terminated strings run across packs)
bytes 16–17  CRC-16 (polynomial x^16 + x^12 + x^5 + 1, inverted), same as the Q channel's CRC

Up to 8 blocks can be present, one per language. The 0x8F packs at the end of each block summarise it.

Image formats handle CD-TEXT in different ways:

Format How CD-TEXT is stored
BIN/CUE As TITLE / PERFORMER / SONGWRITER text commands (a subset), or as a binary .cdt file named by CDTEXTFILE
IMG/CCD/SUB As hex packs in the [CDText] section of the .ccd (16 bytes per entry, without the CRC)
MDS/MDF Unknown. The lead-in is not stored, so CD-TEXT is probably lost
ISO Not supported

MMC's READ TOC/PMA/ATIP command, format 0101b, returns the raw CD-TEXT packs from the lead-in.


4. Q: the position channel #

Q is the important one. It tells the drive where it is: which track, which index, and the time both within the track and from the start of the disc. In the lead-in it carries the TOC. It can also carry the disc's barcode (MCN) and per-track recording codes (ISRC).

4.1 The 96-bit Q frame #

bits    bytes   field
0–3     0 hi    CONTROL (4 bits): track type flags
4–7     0 lo    ADR (4 bits): what kind of data the next 72 bits hold ("mode" of this Q frame)
8–79    1–9     DATA-Q (72 bits): layout depends on ADR
80–95   10–11   CRC-16 over bytes 0–9, stored inverted (one's complement)

Note the byte order: in the raw Q channel CONTROL is the high nibble and ADR the low nibble of byte 0. MMC's READ TOC response puts them the other way round (ADR high, CONTROL low), and so do several image formats that copy the TOC from READ TOC, MDS among them. A raw Q value of 0x41 (control 4, ADR 1) therefore appears as 0x14 in an MDS file.

4.2 CONTROL flags #

Bit (value) Audio track meaning Data track meaning
0 (0x1) Pre-emphasis applied (50/15 µs) Track recorded incrementally (packet writing)
1 (0x2) Digital copy permitted Digital copy permitted
2 (0x4) 0 = audio track 1 = data track
3 (0x8) Four-channel audio (rarely used) reserved (0)

The common values are 0x0 (audio), 0x2 (audio, copy permitted), 0x4 (data) and 0x6 (data, copy permitted). CUE sheets express CONTROL with FLAGS DCP 4CH PRE (and SCMS, which is not a CONTROL bit, see BIN/CUE).

The CONTROL nibble is normally the same in every Q frame of a track, including that track's pregap. On some protected and badly mastered discs it is not. That is one reason preservation formats keep raw subchannel.

4.3 ADR values #

ADR Name Where DATA-Q contents
1 Mode 1: position everywhere Track, index, relative and absolute time (program area) or a TOC entry (lead-in)
2 Mode 2: MCN (Media Catalog Number) program area 13-digit EAN/UPC barcode of the disc
3 Mode 3: ISRC program area of one track 12-character International Standard Recording Code of that track
5 Mode 5: multisession / recordable info lead-in B0, C0, B1–B4, C1 pointers (see Sessions)
4, 6 Other lead-in modes lead-in ADR 4 appears in some video CD/LD-related contexts; ADR 6 has been seen carrying a 24-bit disc ID on CD-R. Aaru reads ADR 6 as a media serial number.

In the program area, ADR 1 frames make up the great majority. The Red Book requires that MCN (ADR 2) and ISRC (ADR 3) frames, when present, appear at least once in every 100 consecutive sectors. A reader therefore has to sample a stretch of the track to find them. The drive repeats the last ADR 1 position, or interpolates it, for the sectors where ADR 2/3 frames take its place.

4.4 CRC #

The 16-bit CRC uses the CCITT polynomial x¹⁶ + x¹² + x⁵ + 1 (0x1021), with initial value 0, processed MSB first, and the result inverted (XOR 0xFFFF) before it is stored big-endian in bytes 10–11. In Rust:

/// CRC of the first 10 Q bytes; compare with u16::from_be_bytes([q[10], q[11]]).
fn q_crc(q: &[u8; 10]) -> u16 {
    let mut crc: u16 = 0;
    for &b in q {
        crc ^= (b as u16) << 8;
        for _ in 0..8 {
            crc = if crc & 0x8000 != 0 { (crc << 1) ^ 0x1021 } else { crc << 1 };
        }
    }
    !crc
}

(libmirage computes the same thing with mirage_helper_calculate_crc16(data, 10, crc16_1021_lut, FALSE, TRUE): not reflected, inverted.)

Worked examples (values in hex):

Q bytes 0–9 Meaning CRC (bytes 10–11)
41 01 01 00 00 00 00 00 02 00 data track 1, index 1, relative 00:00:00, absolute 00:02:00 (LBA 0) 28 32
01 01 00 00 01 74 00 00 00 00 audio track 1, index 0 (pregap), relative 00:01:74 (counting down), absolute 00:00:00 AA B9
41 00 A0 97 26 10 00 01 20 00 lead-in, POINT A0: first track = 1, disc type 0x20 (CD-ROM XA), read at lead-in time 97:26:10 6C EA

Some copy-protection schemes deliberately write bad Q CRCs or altered Q data in specific sectors and check for them at runtime. The best-known example is the PlayStation's LibCrypt. Tools store these in .sbi/.lsd files or in a full .sub.

4.5 Q in the program area (ADR 1) #

All numeric fields are BCD (0x59 means 59).

byte  field
0     CONTROL << 4 | ADR(=1)
1     TNO     Track number 01–99; AA in the lead-out
2     INDEX   Index number 00–99 (00 = pregap / pause; 01 = track start; ...)
3     MIN  ┐
4     SEC  ├ Relative time: time within the current track (from index 1).
5     FRAME┘  In the pregap (index 0) it counts DOWN toward 00:00:00 at index 1.
6     ZERO    00
7     AMIN ┐
8     ASEC ├ Absolute time: time from the start of the program area (00:00:00).
9     AFRAME┘  This is the sector's MSF address; LBA = MSF − 150 (see the LBA page).
10–11 CRC

The relative time is what a CD player's display shows. In a pregap it counts down to zero ("-0:02") and then counts up from index 1. The absolute time is what drives use to seek.

4.6 Q in the program area: MCN (ADR 2) and ISRC (ADR 3) #

MCN (ADR 2):

byte 0     CONTROL << 4 | 2
bytes 1–7  13 BCD digits of the EAN/UPC code (N1..N13), 4 bits each, followed by 4 zero bits
byte 8     ZERO
byte 9     AFRAME: absolute frame (so the frame position is still known)

The MCN is the same for the whole disc.

ISRC (ADR 3): a 12-character code CCOOOYYSSSSS: country (2 letters), owner (3 alphanumeric), year (2 digits), serial (5 digits), for example USRC17607839. The first five characters are packed as 6-bit values ('0'–'9' = 0–9, 'A'–'Z' = 17–42). The seven digits are packed as 4-bit BCD:

byte 0     CONTROL << 4 | 3
bytes 1–8  C1 C2 O1 O2 O3 as 5 × 6 bits (30 bits) + 2 zero bits, then Y1 Y2 S1 S2 S3 S4 S5 as BCD
           nibbles + 4 zero bits
byte 9     AFRAME

libmirage's mirage_helper_subchannel_q_encode_isrc() / ..._decode_isrc() (in lib/cdemu/libmirage/mirage/utils.c) show the exact bit packing.


5. Q in the lead-in: the TOC #

In the lead-in, TNO is always 00 and the meaning of the bytes changes:

byte  field
0     CONTROL << 4 | ADR   (ADR 1 for normal TOC entries, 5 for multisession/recordable info)
1     TNO = 00
2     POINT   what this entry describes (below)
3–5   MIN SEC FRAME  running time within the lead-in (just a position counter; not part of the TOC)
6     ZERO    00 (on DDCD: hour digits)
7     PMIN ┐
8     PSEC ├ value(s) belonging to POINT
9     PFRAME┘
10–11 CRC

5.1 POINT values (ADR 1) #

POINT Meaning PMIN PSEC PFRAME
01–99 Track n Start (index 1) MSF of the track ← ←
A0 First track First track number in this session Disc type: 00 CD-DA or CD-ROM, 10 CD-i, 20 CD-ROM XA 00
A1 Last track Last track number in this session 00 00
A2 Lead-out Start MSF of this session's lead-out ← ←

Each entry is repeated in three consecutive Q frames. The whole set cycles continuously through the lead-in, so a drive that misreads one entry just waits for the next copy. CONTROL on a track entry is that track's control nibble. CONTROL on A0–A2 is usually copied from the first or last track.

5.2 POINT values (ADR 5): multisession and recordables #

POINT Meaning
B0 Multisession pointer: MIN/SEC/FRAME = start time of the next possible program area; ZERO = number of ADR 5 pointers present; PMIN/PSEC/PFRAME = maximum possible start time of the outermost lead-out (disc capacity). FF:FF:FF in MIN/SEC/FRAME means the disc is finalised (closed).
B1 Number of skip intervals / skip tracks (audio CD-R track skipping)
B2–B4 Skip track numbers
C0 MIN = optimum recording power (from ATIP); PMIN/PSEC/PFRAME = start time of the first lead-in on the disc (from ATIP; doubles as a manufacturer code)
C1 Copy of additional ATIP information
01–40 (ADR 5) Skip interval pointers

See Sessions for how B0 and C0 are used.

5.3 The TOC as drives report it #

A drive returns all of these entries through READ TOC/PMA/ATIP, format 0010b ("Full TOC"). Each entry comes back as an 11-byte descriptor:

Session, ADR|CONTROL, TNO, POINT, Min, Sec, Frame, Zero, PMIN, PSEC, PFRAME

The values are binary (not BCD) in the response, except that some drives return BCD when asked.

This descriptor is the root of the TOC storage in two image formats:

  • An MDS data block's bytes 02h–0Bh are exactly bytes 1–10 of this descriptor (ADR|CONTROL, TNO, POINT, Min, Sec, Frame, Zero, PMIN, PSEC, PFRAME). The session number is implied by the session block the data block belongs to.
  • A CCD [Entry n] section has one key per field (Session, ADR, Control, TrackNo, AMin, ASec, AFrame, Zero, PMin, PSec, PFrame), plus ALBA and PLBA, which are the two MSF values converted to LBAs.

6. How image formats store the 96 bytes #

There are several orderings of the same 96 bytes. MMC's READ CD command can return subchannel data in different forms, and image formats inherited them:

6.1 Interleaved ("raw P–W") #

The bytes are kept as they come off the disc: byte i holds bit i of each of the eight subchannels, with P in bit 7.

byte 0:  P[0] Q[0] R[0] S[0] T[0] U[0] V[0] W[0]     (bit 7 .. bit 0)
byte 1:  P[1] Q[1] R[1] ...
...
byte 95: P[95] Q[95] ...

Here X[n] is bit n of subchannel X's 96-bit stream, with bit 0 being the most significant bit of that channel's first byte.

Used by: MDF (when subchannel is stored), CUE CDG tracks, MMC READ CD "raw P–W" (sub-channel selection 001b).

6.2 Linear / deinterleaved ("cooked") #

The 96 bits of each channel are packed into 12 bytes (MSB first), and the channels are written one after another:

bytes  0–11  P channel
bytes 12–23  Q channel   ← bytes 12–21 are the Q frame from section 4, 22–23 its CRC
bytes 24–35  R
bytes 36–47  S
bytes 48–59  T
bytes 60–71  U
bytes 72–83  V
bytes 84–95  W

Used by: CloneCD .sub, Aaru, many dumping tools. It is the easiest form to read: a reader can take Q from bytes 12–23 directly.

6.3 Q only (16 bytes) #

MMC READ CD sub-channel selection 010b returns just the Q channel: 12 bytes (10 data + 2 CRC) plus 4 bytes of padding. Some drives clear the CRC or replace it with their own. A 2368-byte "raw + Q" sector format uses this (libmirage's ISO parser recognises it).

6.4 R–W "cooked" #

READ CD selection 100b returns R–W deinterleaved and error-corrected as CD+G packs (24 × 6-bit symbols × 4). This form is rarely stored in images.

6.5 Converting between interleaved and linear #

From libmirage (mirage_helper_subchannel_interleave / ..._deinterleave), written here in Rust:

/// Interleaved (MDF-style) → linear (CloneCD .sub-style)
fn deinterleave(raw: &[u8; 96]) -> [u8; 96] {
    let mut out = [0u8; 96];
    for ch in 0..8 {              // 0 = P, 1 = Q, ... 7 = W
        let bit = 7 - ch;         // P is bit 7 of each raw byte
        for i in 0..96 {
            let v = (raw[i] >> bit) & 1;
            out[ch * 12 + i / 8] |= v << (7 - (i % 8));
        }
    }
    out
}

/// Linear → interleaved
fn interleave(lin: &[u8; 96]) -> [u8; 96] {
    let mut out = [0u8; 96];
    for ch in 0..8 {
        let bit = 7 - ch;
        for i in 0..96 {
            let v = (lin[ch * 12 + i / 8] >> (7 - (i % 8))) & 1;
            out[i] |= v << bit;
        }
    }
    out
}

To tell the two layouts apart when it isn't stated, compute the Q CRC both ways and see which one matches. libmirage's ISO parser does exactly this for sector 16.

6.6 What is lost without subchannel #

An image without subchannel (ISO, most BIN/CUE, MDF without subchannel) still lets a reader regenerate plausible P and Q data from the TOC: track, index, relative and absolute times. It cannot regenerate:

  • MCN and ISRC frames (unless the descriptor stores them separately, as CUE and CCD do);
  • CD+G graphics;
  • index points that the descriptor didn't record (MDS stores only indexes 0 and 1);
  • deliberate irregularities used for copy protection (bad CRCs, shifted positions, unusual CONTROL values);
  • CD-TEXT. This lives in the lead-in R–W channels, which no common format stores as subchannel. CCD and CUE store it separately.

Sources #