MPEG audio frame header (MP3) encoding and decoding.

Every MP3 frame opens with a 4-byte, bit-packed header. All fields are MSB-first within the 32 bits:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Frame Sync (11)         |Ver|Lyr|P|  Bitrate  |SRat|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Pd|Pr| ChMode|ModeExt|Cp|Or| Emph|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • Frame Sync (11 bits) — always all-ones (MP3_FRAME_SYNC), marking the start of a frame.
  • Ver (mpegVersion, 2 bits) — MPEG version. See MP3_MPEG_VERSION.
  • Lyr (layer, 2 bits) — MPEG layer. See MP3_LAYER.
  • P (protectionAbsent, 1 bit) — 1 means no CRC follows the header, 0 means a 16-bit CRC follows (not covered by this coder).
  • Bitrate (bitrateIndex, 4 bits) — index into a version/layer-specific bitrate table. This package does not resolve it to a kbps value.
  • SRat (samplingRateIndex, 2 bits) — index into a version-specific sample-rate table. This package does not resolve it to a Hz value.
  • Pd (padding, 1 bit) — 1 if the frame carries one extra padding slot, used to make the average bitrate match exactly.
  • Pr (privateBit, 1 bit) — format-defined, not used by the decoder.
  • ChMode (channelMode, 2 bits) — channel mode. See MP3_CHANNEL_MODE.
  • ModeExt (modeExtension, 2 bits) — only meaningful when channelMode is joint stereo; selects which joint-stereo technique applies.
  • Cp (copyright, 1 bit) — 1 if the material is copyrighted.
  • Or (original, 1 bit) — 1 if this is the original media.
  • Emph (emphasis, 2 bits) — de-emphasis to apply on playback.

This package covers the 4-byte frame header only. It does not compute frame length, resolve bitrate/sample-rate table indices to real values, or parse ID3 tags, side information, or audio data — see the package description for the full v0.0.1 scope.

Examples

Round-trip a frame header

import { assertEquals } from "@std/assert";
import {
  MP3_CHANNEL_MODE,
  MP3_FRAME_HEADER_SIZE,
  MP3_FRAME_SYNC,
  MP3_LAYER,
  MP3_MPEG_VERSION,
  mp3FrameHeader,
} from "@binstruct/mp3";

const coder = mp3FrameHeader();
const header = {
  frameSync: MP3_FRAME_SYNC,
  mpegVersion: MP3_MPEG_VERSION.MPEG_1,
  layer: MP3_LAYER.LAYER_3,
  protectionAbsent: 1,
  bitrateIndex: 9,
  samplingRateIndex: 0,
  padding: 0,
  privateBit: 0,
  channelMode: MP3_CHANNEL_MODE.STEREO,
  modeExtension: 0,
  copyright: 0,
  original: 0,
  emphasis: 0,
};

const buffer = new Uint8Array(MP3_FRAME_HEADER_SIZE);
const written = coder.encode(header, buffer);
const [decoded, read] = coder.decode(buffer);

assertEquals(written, MP3_FRAME_HEADER_SIZE);
assertEquals(read, MP3_FRAME_HEADER_SIZE);
assertEquals(decoded, header);