Skip to main content

Crate oxideav_ac4

Crate oxideav_ac4 

Source
Expand description

Pure-Rust Dolby AC-4 audio decoder foundation.

AC-4 is a complex, hierarchical codec — multiple presentations, nested substream descriptors, ASF/ASF-A2/A-SPX coefficient streams driven by huffman-coded scalefactor data, plus an EMDF metadata sidecar carrying DRC / downmix / dialog-norm info. Full decode is weeks of work.

What this crate lands today (per ETSI TS 103 190-1 V1.4.1):

  • Sync framingac4_syncframe() from Annex G: 0xAC40 plain and 0xAC41 CRC-protected, 16-bit frame_size() with 24-bit escape, plus a standalone CRC-16 helper. See sync.

  • Table of contents — full ac4_toc() walker in toc: bitstream_version, sequence_counter, fs_index, frame_rate_index, b_iframe_global, payload_base, per-presentation ac4_presentation_info() (single / multi-substream, configs 0..=5 plus extension escape, HSF extension, pre-virtualised flag, extra EMDF substreams), per-substream ac4_substream_info() (channel_mode prefix decoder, sf_multiplier, bitrate_indicator, content_type w/ language tag, b_iframe), substream_index_table() byte sizes, and the variable_bits(n) codec.

  • Decoderdecoder::Ac4Decoder accepts either a sync-wrapped packet (0xAC40 / 0xAC41 prefix) or a bare MP4-style raw_ac4_frame payload, parses the TOC, and emits a silent S16 AudioFrame with the correct channel count, sample rate, and samples-per-frame for the stream configuration.

  • ASF substream walkerasf::walk_ac4_substream reads ac4_substream() (audio_size + variable_bits extension), the mono/stereo outer audio_data() layers (mono_codec_mode / stereo_codec_mode, spec_frontend, b_enable_mdct_stereo_proc), asf_transform_info() (Tables 99 / 100 / 103) and asf_psy_info() (Table 106 n_msfb_bits + Tables 109/110 n_grp_bits). Surfaces the result through decoder::Ac4Decoder::last_substream so downstream tooling can see the frame’s tool mix and MDCT window grouping without touching Huffman state.

  • Coefficient pipelinehuffman carries the normative ASF_HCB_SCALEFAC / ASF_HCB_SNF / ASF_HCB_1..11 tables from Annex A (plus CB_DIM / UNSIGNED_CB); sfb_offset carries the Annex B.4-B.7 scale-factor-band offset vectors for the 48 kHz family. asf_data walks asf_section_data(), asf_spectral_data() (with Pseudocode-19 dim=2/dim=4 split and Pseudocode-20 codebook-11 extension code), asf_scalefac_data() (dpcm-over-reference scale factors with sf_gain = 2^((sf-100)/4)), and asf_snf_data(). dequantise_and_scale() applies rec_spec = sign(q)|q|^(4/3) then multiplies by the band gain.

  • MDCTmdct implements the reference AC-4 IMDCT (§5.5.2 pseudocodes 60-64, naive O(N^2) complex DFT) plus the KBD window family (§5.5.3, alphas from Table 186) with overlap-add.

  • A-SPX configurationaspx::parse_aspx_config implements the 15-bit aspx_config() element (Table 50, §4.2.12.1) and aspx::parse_companding_control the companding_control() element (Table 49, §4.2.11). The outer audio_data() walker in asf now consumes these for the mono ASPX, stereo ASPX, and stereo ASPX_ACPL_{1,2} I-frame paths. For ASPX_ACPL_{1,2} it now also reads the trailing acpl_config_1ch(PARTIAL) / acpl_config_1ch(FULL) element (§4.2.13.1 Table 59) via acpl::parse_acpl_config_1ch. Exposes the parsed AspxConfig through decoder::Ac4Decoder::last_substream.tools.aspx_config and the A-CPL configs through acpl_config_1ch_partial / acpl_config_1ch_full on asf::SubstreamTools.

  • A-SPX framingaspx::parse_aspx_framing implements aspx_framing() (Table 53, §4.2.12.4) end-to-end for all four interval classes (FIXFIX / FIXVAR / VARFIX / VARVAR) including the 1/2/3-bit aspx_int_class prefix code, the envelope-count derivation for FIXFIX (1 << tmp_num_env with envbits = aspx_num_env_bits_fixfix + 1), Note-1 1-vs-2-bit field widths driven by num_aspx_timeslots, the aspx_tsg_ptr sizing via ceil(log2(num_env + 2)), and the I-frame gate on aspx_var_bord_left for VARFIX / VARVAR. Returns the full aspx::AspxFraming (int_class, num_env, num_noise, freq_res vector, border fields, tsg_ptr). Wired into asf::walk_ac4_substream for both the mono ASPX and stereo ASPX I-frame paths: after companding_control() and the mono_data() / stereo_data() body the walker reads aspx_xover_subband_offset (3 bits) and then aspx_framing(0) (and, for stereo, aspx_balance + conditional aspx_framing(1)). num_aspx_timeslots for the Note-1 field width comes from the TOC’s frame_length via aspx::num_aspx_timeslots (Table 189 × Table 192).

  • A-SPX delta directionaspx::parse_aspx_delta_dir implements aspx_delta_dir(ch) (Table 54, §4.2.12.5): one bit per signal envelope plus one bit per noise envelope. The per- channel AspxDeltaDir drives which ASPX_HCB_*_{F0,DF,DT} codebook the matching aspx_ec_data() path will pull from.

  • A-SPX HF generation / interleaved-waveform coding (mono)aspx::parse_aspx_hfgen_iwc_1ch implements Table 55 (§4.2.12.6): per-subband-group tna_mode, ah_present + conditional add_harmonic[], fic_present + conditional fic_used_in_sfb[], and tic_present + conditional tic_used_in_slot[]. Takes num_sbg_noise, num_sbg_sig_highres, num_aspx_timeslots from the caller.

  • A-SPX HF generation / interleaved-waveform coding (stereo)aspx::parse_aspx_hfgen_iwc_2ch implements Table 56 (§4.2.12.7). Adds per-channel tna_mode[ch][] (with aspx_balance == 1 mirroring channel 0 into channel 1), per-channel aspx_ah_left / _right gates, aspx_fic_present plus per-channel fic_left / fic_right gates, and the aspx_tic_copy / aspx_tic_left / aspx_tic_right TIC gating (including mirroring left-channel TIC into right when tic_copy is set).

  • A-SPX Huffman infrastructureaspx::AspxHcb is a (len[], cw[], cb_off) codebook helper: the symbol decoder walks one bit at a time until a (len == width, cw == code) match lands, then returns symbol_index - cb_off as the delta. All 18 Annex A.2 codebooks (Tables A.16..=A.33) are transcribed in aspx_huffman — six (F0, DF, DT) triples covering envelope-LEVEL / envelope-BALANCE @ 1.5 dB / 3 dB plus noise-LEVEL / noise-BALANCE. A aspx::HuffmanCodebookId enum plus aspx::lookup_aspx_hcb resolve the get_aspx_hcb(data_type, quant_mode, stereo_mode, hcb_type) tuple from §5.7.6.3.4 Pseudocode 79.

  • A-SPX entropy coded dataaspx::parse_aspx_ec_data implements aspx_ec_data() (Table 57, §4.2.12.8) on top of aspx::parse_aspx_huff_data (Table 58) — per-envelope loop that picks F0/DF/DT codebook per direction and returns a vector of aspx::AspxHuffEnvs.

  • A-SPX master freq-scale derivationaspx::derive_aspx_frequency_tables implements §5.7.6.3.1 Pseudocodes 67, 68, 69 and 70: picks between aspx::ASPX_SBG_TEMPLATE_HIGHRES and aspx::ASPX_SBG_TEMPLATE_LOWRES by aspx_master_freq_scale, trims with aspx_start_freq / aspx_stop_freq into the master subband-group table, then applies aspx_xover_subband_offset to produce the high-res / low-res signal tables. The noise subband-group table follows Pseudocode 70’s max(1, floor(aspx_noise_sbg * log2(sbz/sbx) + 0.5)) count rule and is clamped to num_sbg_noise <= 5. Returns aspx::AspxFrequencyTables containing master / high-res / low-res / noise border tables plus sba, sbz, sbx, num_sb_aspx and an aspx::AspxSbgCounts ready to feed aspx::parse_aspx_ec_data.

  • Full A-SPX data-path wiringasf::walk_ac4_substream now runs the whole aspx_data_1ch() / aspx_data_2ch() body on I-frame ASPX substreams: aspx_xover_subband_offsetaspx_framing (+ stereo aspx_balance / second framing) → aspx_delta_dir → derived aspx::AspxFrequencyTablesaspx_hfgen_iwc_1ch() / aspx_hfgen_iwc_2ch()aspx_ec_data() SIGNAL and NOISE per channel. All parsed data lands on asf::SubstreamTools alongside the existing framing / delta-dir / qmode fields.

  • QMF analysis + synthesis filter bankqmf::QWIN carries the 640-coefficient QMF prototype window from Annex D.3. qmf::qmf_analysis_slot + qmf::QmfAnalysisBank implement the §5.7.3.2 Pseudocode 65 forward transform (windowing + 5-fold time-fold to vector u + 64-point complex modulation); qmf::qmf_synthesis_slot + qmf::QmfSynthesisBank implement the matching §5.7.4.2 Pseudocode 66 inverse transform (shifted 1 280-sample qsyn_filt delay line + 128-point modulation + folded-tap 64-way tap sum). The analysis/synthesis pair achieves ~80 dB PSNR end-to-end roundtrip on sine and noise test signals (unit tests in qmf).

  • A-SPX HF regeneration scaffoldaspx::derive_patch_tables implements §5.7.6.3.1.4 Pseudocode 71 (patch subband-group table derivation). aspx::hf_tile_copy implements a simplified §5.7.6.4.1.4 Pseudocode 89 high-band tile copy via the patch table (no chirp/alpha0/alpha1 tonal adjust). The full TNS body lives in the dedicated aspx_tns module — see below. aspx::apply_flat_envelope_gain is a one-gain scaffold kept as a fallback for the §5.7.6.4.2 HF envelope adjustment tool. Together with the QMF bank these form an end-to-end bandwidth- extension pipeline: PCM → QMF analysis → low-band truncate → HF tile-copy → QMF synthesis → non-silent PCM.

  • A-SPX TNS (chirp + α0 + α1)aspx_tns implements the full §5.7.6.4.1.2 / .1.3 / .1.4 complex-covariance Temporal Noise Shaping path: pre-flatten gain vector (aspx_tns::compute_preflat_gains, Pseudocode 85), complex covariance matrix over Q_low_ext (aspx_tns::compute_covariance, Pseudocode 86), α0 / α1 LPC coefficients with the EPSILON_INV slack and the |α|≥4 fallback (aspx_tns::compute_alphas, Pseudocode 87), per-noise-subband- group chirp factors via the Table 195 tabNewChirp lookup with attack / decay smoothing (aspx_tns::chirp_factors, Pseudocode 88), and the full HF signal creation that adds chirp * α0 * Q_low[n-2] + chirp² * α1 * Q_low[n-4] plus the optional pre-flatten divide (aspx_tns::hf_tile_tns, Pseudocode 89). Per-channel state (aspx_tns::AspxTnsState) carries aspx_tna_mode_prev[] / prev_chirp_array[] plus the tail of the previous interval’s Q_low for the ts_offset_hfadj = 4 look-back. The decoder auto-selects the TNS path when the parsed aspx_hfgen_iwc_* provides aspx_tna_mode[ch][] and the framing is FIXFIX; otherwise it falls back to the bare tile copy.

  • A-SPX HF envelope adjustment (per-envelope gain)aspx::AspxEnvelopeAdjuster implements §5.7.6.4.2 Pseudocodes 90 + 91 + 95 (non-harmonic, non-limited path): delta-decode aspx_data_sig / aspx_data_noise (Pseudocodes 80 / 81) via aspx::delta_decode_sig / aspx::delta_decode_noise, dequantize to scf_sig_sbg / scf_noise_sbg (Pseudocodes 82 / 83) via aspx::dequantize_sig_scf / aspx::dequantize_noise_scf, estimate the actual HF envelope energy (aspx::estimate_envelope_energy), map subband-group scale factors onto QMF subbands (aspx::map_scf_to_qmf_subbands), then compute per-subband compensatory gains (aspx::compute_sig_gains) = sqrt(scf_sig / ((1 + est) * (1 + scf_noise))). The per-envelope gains are applied via aspx::apply_envelope_gains using the FIXFIX Table-194 atsg_sig / atsg_noise borders derived by aspx::derive_fixfix_atsg. The decoder auto-selects the per-envelope path when the substream parsed FIXFIX framing plus matching envelope deltas, and falls back to apply_flat_envelope_gain(0.5) otherwise.

  • ASPX decoder wiringdecoder::Ac4Decoder now routes ASPX substreams through the extension pipeline: when an I-frame ASPX substream produces derived aspx_frequency_tables, the decoder takes the IMDCT low-band PCM, runs QMF analysis → tile-copy HF regen → per-envelope gain (or flat-gain fallback) → QMF synthesis, and emits bandwidth-extended PCM instead of silence.

  • Dialogue Enhancement (DE) parserde::parse_dialog_enhancement walks the dialog_enhancement(b_iframe) element (§4.2.14.11 Table 76) end-to-end: b_de_data_present gate, optional I-frame de_config() (§4.2.14.12 Table 77, de_method / de_max_gain / de_channel_config), and the per-frame de_data() payload (§4.2.14.13 Table 78) including the cross-channel de_keep_pos_flag + de_mix_coef[12]_idx panning parameters, the de_keep_data_flag re-use gate, the de_ms_proc_flag M/S processing flag, and the per-channel per-band de_par[ch][band] matrix decoded via the Annex A.4 Huffman codebooks (de_huffman::de_abs_huffman / de_huffman::de_diff_huffman, Tables A.58..A.61). The four codebooks (DE_HCB_ABS_0 / DE_HCB_DIFF_0 / DE_HCB_ABS_1 / DE_HCB_DIFF_1) are transcribed verbatim from the normative ETSI accompaniment file ts_10319001v010401p0-tables.c and are verified by Kraft-sum = 1 and prefix-code unit tests.

  • DRC metadata parserdrc::parse_drc_frame walks the drc_frame() element (§4.2.14.5 Table 70) end-to-end: b_drc_present gate, optional I-frame drc_config() (§4.2.14.6 Table 71) including up to eight drc_decoder_mode_config() blocks with all three branches (drc_repeat_profile_flag, drc_default_profile_flag, explicit drc_compression_curve()), the full drc_compression_curve() with optional boost / cut sections and per-mode time-constant block (§4.2.14.8 Table 73), and the per-frame drc_data() payload (§4.2.14.9 Table 74) that pulls one drc_gains() entry per gainset mode. drc::parse_drc_gains decodes the seven-bit drc_gain_val seed plus all (ch, band, sf) deltas through the Annex A.5 DRC_HCB Huffman codebook (huff_decode_diff per §4.3.10.8.3), with the per-band / per-channel ref_drc_gain reset semantics from Table 75 honoured. The Annex A.5 codebook itself (drc_huffman::DRC_HCB_LEN / drc_huffman::DRC_HCB_CW) is transcribed verbatim from the ETSI accompaniment file ts_10319001v010401p0-tables.c and is verified by a Kraft-sum = 1 unit test (complete prefix code) plus an explicit prefix- code check.

  • Metadata walkermetadata::parse_metadata implements the outer metadata(b_iframe) element (§4.2.14.1 Table 66) end-to-end: basic_metadata(channel_mode) (§4.2.14.2 Table 67) including the b_more_basic_metadata block with optional further_loudness_info (§4.2.14.3 Table 68), the stereo / multi-channel downmix info tracks, the 5.x-only pre_dmixtyp_5ch / pre_upmixtyp_5ch and 7.x-only pre_upmixtyp_3_4 / pre_upmixtyp_3_2_2 paths, and the b_dc_blocking flag; extended_metadata(channel_mode, b_associated, b_dialog) (§4.2.14.4 Table 69) including the per-channel b_*_active / b_*_has_dialog channels-classifier block; the tools_metadata_size_value (7-bit + optional variable_bits(3) << 7 extension) hint; dispatch into drc::parse_drc_frame and de::parse_dialog_enhancement; and the trailing b_emdf_payloads_substream flag. The walker chains a metadata::MetadataState forward across frames so non-I frames re-use the most recent drc_config() / de_config() per the bitstream’s gating semantics. After DRC + DE consume their bytes the walker reconciles against tools_metadata_size and skips any trailing reserved bits inside the announced envelope, providing forward compatibility against future tools-metadata extensions.

  • A-CPL parameter↔QMF subband mappingacpl::sb_to_pb implements §5.7.7.2 Table 197 for all four acpl_num_param_bands configurations (15 / 12 / 9 / 7), the last piece needed to wire acpl_data_*ch() parameters through to QMF subbands during synthesis.

  • A-CPL synthesis mathacpl_synth implements the §5.7.7 QMF-domain synthesis pipeline end-to-end: acpl_synth::differential_decode (§5.7.7.7 Pseudocode 121) recovers absolute acpl_<SET>_q arrays from the Huffman deltas produced by acpl::parse_acpl_data_1ch / acpl::parse_acpl_data_2ch, with state carried across parameter sets and AC-4 frames via acpl_synth::AcplDiffState; acpl_synth::dequantize_alpha_beta / acpl_synth::dequantize_beta3 / acpl_synth::dequantize_gamma apply Tables 203-208 (with the cross-coupled Tables 203/204 and 205/206 ibeta linkage); acpl_synth::interpolate (§5.7.7.3 Pseudocode 109) covers both smooth (linear-between-borders) and steep (timeslot-keyed) per-QMF-subsample interpolation; acpl_synth::InputSignalModifier (§5.7.7.4.2 Pseudocode 111) implements the three frequency-region all-pass IIR decorrelators D0 / D1 / D2 over Tables 198-201; acpl_synth::TransientDucker (§5.7.7.4.3 Pseudocodes 112-114) carries the per-pb peak-decay / smooth state and emits duck_gain[pb]; acpl_synth::acpl_module (§5.7.7.5 Pseudocode 116) and acpl_synth::run_pseudocode_115_pair (Pseudocode 115) wire the channel-pair element together end-to-end with the acpl_qmf_band M/S split below the threshold and the alpha/beta-modulated decorrelator mix above.

  • A-CPL decoder wiringasf::walk_ac4_substream now consumes the full aspx_data_1ch() (Table 51) + acpl_data_1ch() (Table 61) tail of the ASPX_ACPL_2 stereo path: the mono MDCT body parser ([asf::parse_aspx_acpl2_mdct_body] internal) walks the spec_frontend; sf_info; sf_data shape, then the shared [asf::parse_aspx_data_1ch_body] helper reads the leading xover-offset + framing + delta-dir + hfgen + ec_data, and finally acpl::parse_acpl_data_1ch is invoked with num_bands = acpl_num_param_bands and start_band = sb_to_pb(acpl_qmf_band, num_param_bands) per Table 61. The parsed payload lands on asf::SubstreamTools::acpl_data_1ch. decoder::Ac4Decoder now drives acpl_synth::run_acpl_1ch_pcm (mono PCM → QMF analysis → §5.7.7.5 channel-pair element → QMF synthesis × 2) when the substream provides an acpl_config_1ch plus acpl_data_1ch, emitting two PCM channels in place of the duplicate-of-primary fallback. Per-substream acpl_synth::AcplSubstreamState (alpha-diff + beta-diff + AcplCpeState decorrelator + ducker) lives on the decoder so IIR delay-lines and acpl_<SET>_q_prev survive across frames. ASPX_ACPL_1’s joint-MDCT residual layer (b_dual_maxsfb = 1 with chparam_info()) now walks end-to-end as of round-18: asf::parse_chparam_info (§4.2.10.1 Table 47) + asf::parse_sap_data (Table 48) drive the joint shell, parse_aspx_acpl1_mdct_body walks the dual M/S residuals (long frame + single window group), and the decoder feeds both into acpl_synth::run_acpl_1ch_pcm_stereo (x0 = M, x1 = S into Pseudocode 116) for the full stereo synth.

  • Speech Spectral Frontend (SSF) tables + arithmetic decoder core — the full Annex C scalar-table inventory now lands in ssf_tables: POST_GAIN_LUT (C.1), PRED_GAIN_QUANT_TAB (C.3), PRED_RFS_TABLE / PRED_RTS_TABLE (C.4 / C.5), the 705-entry CDF_TABLE (C.7), PREDICTOR_GAIN_CDF_LUT (C.8), ENVELOPE_CDF_LUT (C.9), the 256-entry DITHER_TABLE (C.10) and RANDOM_NOISE_TABLE (C.11), STEP_SIZES_Q4_15 (C.12), AC_COEFF_MAX_INDEX (C.13), and the four SLOPES_* / OFFSETS_* dB↔linear LUTs (C.14). The 37 SSF prediction- coefficient matrices from Annex C.6 (~22 KB total) live in ssf_pred_coeff addressable via ssf_pred_coeff::ssf_pred_coeff_mat. Every byte in every table is validated against the ETSI accompaniment file by the validate_ssf_* integration tests. The arithmetic decoder itself (ssf_ac::AcState) implements §5.2.8 Pseudocodes 41-47 (AcDecoderInit / AcDecodeTarget / AcDecode / AcDecodeSymbolExtCdf / AcDecodeFinish) plus Pseudocode 51-53 (Idx2Reconstruction + CdfEst for the computed-CDF transform-coefficient path) and the §5.2.8.3 random-number generator (ssf_ac::SsfRandGenState, Pseudocodes 54-57). Wired-up convenience functions: ssf_ac::decode_envelope_indices (Pseudocode 48), ssf_ac::decode_predictor_gain (Pseudocode 49), ssf_ac::decode_coefficient_indices (Pseudocode 50). The ssf_data() / ssf_granule() / ssf_st_data() / ssf_ac_data() bitstream walkers (Tables 43-46) are the next round’s scope — the AC decoder building blocks are now in place.

  • SSF bitstream walkerssf::parse_ssf_data / ssf::parse_ssf_granule / ssf::parse_ssf_st_data / ssf::parse_ssf_ac_data implement Tables 43-46 end-to-end. The walker derives the SSF block layout per Table 112 (48 kHz family) via ssf::SsfFrameConfig::from_frame_len_base, builds start_bin[] / end_bin[] / num_bins from the Annex C.1 bandwidths matrix (ssf::SSF_BANDWIDTHS) per §4.3.7.5 Pseudocode 7, drains the per-block predictor / static fields, and drives the §5.2.8 arithmetic decoder (ssf_ac::AcState) for env_curr_ac_bits / env_startup_ac_bits / predictor_gain_ac_bits[block] / q_mdct_coefficients_ac_bits[block]. Per-channel ssf::SsfChannelState carries forward dither / noise RNG state (reset per SSF-I-frame per Pseudocode 55) plus prev_pred_lag_idx / last_num_bands / env_prev[]. The walker is wired into asf::walk_ac4_substream for both the mono path (spec_frontend == SSF no longer returns Unsupported) and the split-MDCT stereo + ASPX_ACPL_1 paths (per-channel SSF/ASF selection). Parsed payload lands on asf::SubstreamTools::ssf_data_primary / ssf_data_secondary for downstream synthesis.

Known gaps (Unsupported or stubbed):

  • Short / grouped frames (num_window_groups > 1) — round 28 lands the mono / stereo sf_data(ASF) walker per Tables 39-42 (each asf_*_data() body has its own outer for (g; ...) loop, with a single reference_scale_factor and single b_snf_data_exists at the head). Multichannel layouts (5.X / 7.X) still use the r24 per-group interleaved walker. MDCT synthesis for the per-group spectra (concatenated group-major in tools.scaled_spec_primary / tools.scaled_spec_secondary) is not yet hooked through the decoder.
  • Remaining §5.7.6.4 A-SPX HF regeneration — non-FIXFIX interval classes (FIXVAR / VARFIX / VARVAR) still fall back to the flat-gain scaffold; the limiter (§5.7.6.4.2.2) and TNS (§5.7.6.4.1) paths only run on FIXFIX framing today. The TNS pipeline is fully implemented in aspx_tns but per-channel master_reset semantics (resetting prev_chirp_array / the Q_low_prev history) when a new substream starts mid-stream isn’t surfaced through the decoder API yet.
  • A-CPL data-path decoder hookup — ASPX_ACPL_2 (mono MDCT body) was fully wired in round-17, and ASPX_ACPL_1 (joint-MDCT body with chparam_info() driving M/S coupling) is now wired in round-18: parser walks the full dual-residual body, decoder IMDCTs both M and S spectra and feeds them as x0 / x1 into the §5.7.7.5 channel-pair element. Round-21 lands the §5.7.7.6.2 ASPX_ACPL_3 transform-matrix synthesis math (Transform(), ACplModule2(), ACplModule3(), run_pseudocode_118_5x() — Pseudocodes 118 / 119); the 5_X-walker glue from the bitstream into the new transform synthesis is the next round’s scope. Multichannel 5_X_codec_mode = ASPX_ACPL_1 / ASPX_ACPL_2 wrappers (Pseudocode 117) are still pending — the building blocks are all in place but the 5-input wrapper is not wired.
  • Speech Spectral Frontend (SSF) PCM synthesis — round 31 lands the §5.2.3-5.2.7 chain in ssf_synth: envelope decoder (ssf_synth::decode_envelope / ssf_synth::interpolate_envelope / ssf_synth::decode_gains / ssf_synth::refine_envelope — Pseudocodes 4a-4d), predictor parameter calculation (ssf_synth::decode_predictor — Pseudocode 4e), helper variables and lossless-decoding allocation table (ssf_synth::compute_helpers / ssf_synth::build_alloc_table — Pseudocodes 26 + 31 no-rfu path), inverse quantizer (ssf_synth::inverse_quantize_block / ssf_synth::mmse_laplace — Pseudocodes 32 / 33), inverse heuristic scaling (ssf_synth::inverse_heuristic_scale — Pseudocode 34), C-matrix reconstruction (ssf_synth::build_c_matrix — Pseudocode 39), subband predictor (ssf_synth::SubbandPredictorState::run — Pseudocodes 35-37) and inverse flattening (ssf_synth::inverse_flatten — Pseudocode 38). The decoder (decoder::Ac4Decoder::receive_frame) now consumes tools.ssf_data_primary / tools.ssf_data_secondary and runs synthesize_ssf_data → IMDCT → KBD overlap-add per channel, producing real PCM in place of silence for SSF substreams. The heuristic-scaling helpers (§5.2.5.2.2 Pseudocodes 27 / 28 / 29 / 30) are deferred — the spec’s f_rfu == 0 short-circuit short-circuits to the no-heuristic path the synth already supports, covering any block with the predictor disabled.
  • Spectral noise fill synthesis — asf_snf_data() parses the Huffman-coded indices but doesn’t inject shaped noise into zero bands yet.
  • emdf_payloads_substream() parsing — the outer metadata::parse_metadata walker errors out when b_emdf_payloads_substream == 1 rather than mis-aligning the bitstream. Implementing §4.2.4.4 / §4.2.14.14 EMDF payloads is the next step before real-bitstream metadata can fully round-trip. walk_ac4_substream itself doesn’t yet invoke the metadata walker — that wiring is the follow-up to this round.
  • TS 103 190-2 IFM (immersive / object) decoding — round 47 lands the v2 TOC walker (bitstream_version >= 2 dispatch in toc::parse_ac4_toc running ac4_presentation_v1_info() per §6.2.1.3 + ac4_substream_group_info() per §6.3.2.5 + ac4_substream_info_chan() per §6.2.1.8) and the matching encoder_ims::Ac4ImsEncoder tone-encoder (encoder_ims::Ac4ImsEncoder::encode_frame_mono_tone / encoder_ims::Ac4ImsEncoder::encode_frame_mono_tone_at_hz) that produces a v2 frame whose mono SIMPLE/ASF audio body round-trips through decoder::Ac4Decoder to non-silent PCM. Object / a-joc substream parsing inside ac4_substream_group_info() is still deferred — the walker surfaces Unsupported on the first object substream.
  • Encoder for arbitrary PCM input — round 47 ships a closed-form canned-tone encoder (encoder_ims::build_mono_simple_asf_tone_body). MDCT analysis, scalefactor selection, and ASF entropy coding for arbitrary input PCM are the next step.

The decoder emits real PCM for long-frame, single-window-group mono and stereo SIMPLE/ASF streams. The stereo path covers both the split-MDCT layout (two independent ASF spectra) and the joint b_enable_mdct_stereo_proc == 1 mode (shared sections + scalefactors, two residuals, per-sfb ms_used[] inverse L = M + S / R = M - S per §7.5). Everything else falls back to silence with a correctly-shaped AudioFrame.

Modules§

acpl
Advanced Coupling (A-CPL) parser plumbing — ETSI TS 103 190-1 §4.2.13 / §4.3.11.
acpl_huffman
A-CPL (Advanced Coupling) Huffman codebooks (Annex A.3, Tables A.34..A.57 of ETSI TS 103 190-1 V1.4.1).
acpl_synth
A-CPL (Advanced Coupling) QMF synthesis math — ETSI TS 103 190-1 §5.7.7.
asf
AC-4 Audio Spectral Frontend (ASF) substream baseline.
asf_data
ASF data-payload parsers — the Huffman-driven body of asf_section_data(), asf_spectral_data(), asf_scalefac_data() and asf_snf_data() (ETSI TS 103 190-1 §4.2.8.3 / §4.2.8.4 / §4.2.8.5 / §4.2.8.6 and §5.1.2 / §5.1.3).
aspx
AC-4 Advanced Spectral Extension (A-SPX) parameter parsing.
aspx_huffman
A-SPX envelope / noise Huffman codebooks (Annex A.2, Tables A.16..A.33).
aspx_limiter
A-SPX gain limiter — ETSI TS 103 190-1 §5.7.6.4.2.2 Pseudocodes 96..101 plus the §5.7.6.3.1.5 sbg_lim derivation (Pseudocodes 72..74).
aspx_noise
A-SPX noise generator (§5.7.6.4.3) + Annex D.2 NoiseTable.
aspx_tns
A-SPX Temporal Noise Shaping (complex-covariance LPC + chirp).
aspx_tone
A-SPX tone generator (§5.7.6.4.4) + Table 196 SineTable.
de
Dialogue Enhancement (DE) parser — §4.2.14.11..13 syntax, §4.3.14 semantics. Walks dialog_enhancement(b_iframe) (Table 76) end-to-end, including de_config() (Table 77, §4.3.14.3) and de_data() (Table 78, §4.3.14.4) plus the de_par[ch][band] decoding that runs through the Annex A.4 Huffman codebooks (crate::de_huffman).
de_huffman
Dialogue Enhancement (DE) Huffman codebooks (Annex A.4, Tables A.58..A.61 of ETSI TS 103 190-1 V1.4.1).
decoder
Foundation AC-4 decoder.
drc
Dynamic Range Control (DRC) metadata parsing — §4.2.14.5..10 syntax, §4.3.13 semantics. Pure parser: walks the bitstream and surfaces the decoded fields, plus the per-(channel, subframe, band) DRC gain matrix decoded via the Annex A.5 Huffman codebook (crate::drc_huffman).
drc_huffman
DRC Huffman codebook (Annex A.5, Table A.62 of ETSI TS 103 190-1).
emdf
EMDF payloads substream parser — TS 103 190-1 V1.4.1.
encoder_acpl3
5_X ASPX_ACPL_3 multichannel encoder per ETSI TS 103 190-1 §4.2.6.6 Table 25 row case ASPX_ACPL_3: (round 95).
encoder_asf
Forward ASF entropy coding for the AC-4 IMS encoder (round 48).
encoder_ims
AC-4 IMS (Immersive Multichannel Service) encoder scaffold.
encoder_mdct
Forward MDCT analysis for the AC-4 IMS encoder (round 48).
huffman
ASF Huffman codebooks from ETSI TS 103 190-1 Annex A.
mch
Multichannel 5_X_channel_element walker family — round 20 wiring.
mdct
AC-4 IMDCT and KBD window synthesis (ETSI TS 103 190-1 §5.5).
metadata
Outer §4.2.14.1 metadata() walker — TS 103 190-1 V1.4.1 Table 66.
qmf
AC-4 QMF analysis / synthesis filter-bank (§5.7.1 – 5.7.4).
sfb_offset
Scale-factor-band offset tables (Annex B.4-B.7 of ETSI TS 103 190-1).
ssf
AC-4 Speech Spectral Frontend (SSF) bitstream walker.
ssf_ac
AC-4 Speech Spectral Frontend (SSF) arithmetic decoder.
ssf_pred_coeff
AC-4 Annex C.6 — SSF prediction-coefficient matrices.
ssf_synth
AC-4 Speech Spectral Frontend (SSF) synthesis chain.
ssf_tables
AC-4 Annex C scalar lookup tables (TS 103 190-1 V1.4.1).
sync
AC-4 sync-frame helpers (TS 103 190-1 Annex G).
tables
Normative AC-4 lookup tables (ETSI TS 103 190-1 Annex B and §4.3.6).
toc
ac4_toc() — AC-4 table-of-contents parser.

Constants§

CODEC_ID_STR
Canonical codec id.

Functions§

register
Unified registration entry point — installs AC-4 into the codec sub-registry of the supplied oxideav_core::RuntimeContext.
register_codecs
Register the AC-4 decoder in a codec registry.