Skip to main content

Ac4ImsEncoder

Struct Ac4ImsEncoder 

Source
pub struct Ac4ImsEncoder {
    pub bitstream_version: u8,
    pub sequence_counter: u16,
    pub fs_index: u8,
    pub frame_rate_index: u8,
    pub b_iframe_global: bool,
    pub channel_mode_value: u8,
    pub channel_mode_bits: u8,
    pub mdct_state: Option<EncoderMdctState>,
    pub mdct_state_r: Option<EncoderMdctState>,
    pub mdct_states_multi: Vec<EncoderMdctState>,
}
Expand description

Encoder-side builder for AC-4 IMS frames. One instance per audio stream — carries the 10-bit sequence_counter rolling counter and the canonical frame layout (sample rate, frame-rate index, channel mode) so each encode_frame() call produces a structurally-valid output frame ready to wrap in a sync-frame (0xAC40 / 0xAC41) or hand to an MP4 muxer.

Round 46 lands the Auditor-mode bit layout per ETSI TS 103 190-2 §6.2.1.1 — the audio body itself is all-zero placeholder bits.

Fields§

§bitstream_version: u8

bitstream_version value to emit (TS 103 190-2 Table 74). 0 selects the TS 103 190-1 v0 path (ac4_presentation_info() per-pres); 2 selects the IMS path (ac4_presentation_v1_info() + ac4_substream_group_info()).

§sequence_counter: u16

Rolling 10-bit sequence_counter field — wraps modulo 1024.

§fs_index: u8

fs_index (1 b): 0 → 44.1 kHz, 1 → 48 kHz.

§frame_rate_index: u8

frame_rate_index (4 b) per Table 83 / 84.

§b_iframe_global: bool

b_iframe_global flag for this frame.

§channel_mode_value: u8

Channel mode prefix code per Table 85 (TS 103 190-1) / Table 78 (TS 103 190-2): 0b0 → mono, 0b10 → stereo, etc. Encoded as the literal prefix in the low-order bits of channel_mode_value with the bit count in channel_mode_bits.

§channel_mode_bits: u8

Bit-width of channel_mode_value (1..=11).

§mdct_state: Option<EncoderMdctState>

Forward-MDCT analysis state for encode_frame_pcm(). Carries the previous frame’s N PCM samples so the 50% TDAC overlap runs correctly across frames. Lazy-initialised on first use.

§mdct_state_r: Option<EncoderMdctState>

Forward-MDCT analysis state for the secondary (right) channel of encode_frame_pcm_stereo(). Identical role to mdct_state but for the second channel — separate so 50% TDAC overlap is per-channel.

§mdct_states_multi: Vec<EncoderMdctState>

Forward-MDCT analysis state for the multichannel encoder paths (encode_frame_pcm_5_0() and any future N>2 variants). One EncoderMdctState per output channel — separate so 50% TDAC overlap continuity is preserved per channel across frames. Lazy- initialised on first use; grown to the required channel count.

Implementations§

Source§

impl Ac4ImsEncoder

Source

pub fn new() -> Self

New encoder defaulting to the smallest-valid IMS shape: bitstream_version = 2, sequence_counter = 0, 48 kHz, 24 fps (frame_rate_index = 1), b_iframe_global = 1, mono channel mode (0b0, 1 b).

Source

pub fn with_v0(self) -> Self

Switch to a TS 103 190-1 v0 frame layout. The decoder in this crate parses v0 today; v2 is structurally emitted but not yet re-parsed end-to-end.

Source

pub fn with_stereo(self) -> Self

Stereo channel mode (0b10, 2 b).

Source

pub fn with_5_0(self) -> Self

5.0 channel mode (0b1101, 4 b) per Table 85 — channel_mode 3 — the 5.0 surround layout (L, R, C, Ls, Rs) without LFE. Drives the decoder’s 5_X_channel_element() walker for channels == 5 (no b_has_lfe block) and the corresponding dispatch_5x_cfg3_simple_aspx PCM output path.

Source

pub fn with_5_1(self) -> Self

5.1 channel mode (0b1110, 4 b) per Table 85.

Source

pub fn with_7_0(self) -> Self

7.0 (3/4/0) channel mode (0b1111000, 7 b) per ETSI TS 103 190-1 §4.3.3.7.1 Table 88 — channel_mode value 1111000 → ch_mode 5 → 7 channels with layout L, C, R, Ls, Rs, Lb, Rb. Drives the decoder’s 7_X_channel_element() walker for channels == 7 (no b_has_lfe — that branch is gated on channel_mode 6 / 7.1) per §4.2.6.14 Table 33. The decoder’s internal coding order for the inner five_channel_data() is [L, R, C, Ls, Rs] per Table 180 (the inner SCE order differs from the surface Table 88 listing’s L, C, R ordering — the decoder treats the inner five_channel_data slots as L/R/C/Ls/Rs).

Source

pub fn with_7_1(self) -> Self

7.1 (3/4/0.1) channel mode (0b1111001, 7 b) per ETSI TS 103 190-1 §4.3.3.7.1 Table 88 — channel_mode value 1111001 → ch_mode 6 → 8 channels with layout L, C, R, Ls, Rs, Lb, Rb, LFE. Drives the decoder’s 7_X_channel_element() walker for channels == 8 (with b_has_lfe) per §4.2.6.14 Table 33. The decoder’s internal coding order for the inner five_channel_data() is [L, R, C, Ls, Rs] per Table 180 (the inner SCE order differs from the surface Table 88 listing’s L, C, R ordering — the decoder treats the inner five_channel_data slots as L/R/C/Ls/Rs).

Source

pub fn encode_frame(&mut self, body_padding_bytes: usize) -> Vec<u8>

Encode one Auditor-mode frame: emits a raw_ac4_frame() payload (TOC + minimum-viable substream skeleton) and bumps sequence_counter. Returns the produced bytes.

Source

pub fn encode_frame_v0(&mut self, body_padding_bytes: usize) -> Vec<u8>

Encode the same frame at bitstream_version = 0 regardless of the encoder’s configured version — used by the round-trip test to feed a TS 103 190-1-decodable frame back through crate::toc::parse_ac4_toc.

Source§

impl Ac4ImsEncoder

Source

pub const STEREO_JOINT_MS_CORRELATION_THRESHOLD: f32 = 0.7

Round-52 heuristic threshold for joint M/S coding. When the per-SFB average Pearson correlation between L and R MDCT spectra exceeds this value, the encoder switches to Path B (joint M/S CPE, b_enable_mdct_stereo_proc == 1); otherwise Path A (split-MDCT, 2× SCE) is used. The 0.7 threshold matches the spec’s §5.3 guidance plus the headline number cited in this crate’s round-52 task brief.

Source

pub fn encode_frame_mono_tone( &mut self, tone_cb_idx: usize, tone_pair_idx: u32, ) -> Vec<u8>

Encode one IMS v2 frame containing a mono SIMPLE/ASF audio substream that injects a single quantised spectral tone (per tone_cb_idx from the ETSI Annex A HCB5 codebook). The decoder dequantises the tone via rec_spec = sign(q)|q|^(4/3) and the IMDCT + KBD windowing produce real, non-silent PCM.

This is the canned-tone closed-form encoder mentioned in round-47 scope: full MDCT analysis + scalefactor optimisation + ASF entropy coding for arbitrary PCM input is deferred. The shape of this method (input PCM → bytes) is reserved for that future work; for now it ignores its _input_pcm argument and emits the canned tone payload.

Per ETSI TS 103 190-1 §5.7 + §5.8.

Source

pub fn encode_frame_pcm(&mut self, frame: &[f32]) -> Vec<u8>

Encode one IMS v2 mono frame from arbitrary float PCM input (range [-1.0, 1.0]). Returns the produced frame bytes.

Pipeline (round 48):

  1. Forward MDCT analysis with KBD windowing across the 50% TDAC boundary (carries prior-frame N samples in the per-encoder EncoderMdctState).
  2. Per-band scalefactor selection (greedy nearest power-of-two that keeps |q| within the chosen Huffman codebook’s bound).
  3. Quantisation per Pseudocode 18 inverse: q = round(sign(c) * (|c|/sf_gain)^(3/4)).
  4. ASF entropy coding via HCB5 (signed dim=2, q-range -4..=+4).
  5. Wrap in v2 IMS TOC + single-substream-group audio_size body.

Frame length is derived from the encoder’s (fs_index, frame_rate_index) pair via crate::toc::frame_rate_entry. For the default mono 48 kHz / 24 fps configuration frame.len() is 1920 samples and max_sfb is 10 (matching the canned-tone helper).

Per ETSI TS 103 190-1 §5.5 (MDCT) + §5.7 / §5.8 (SIMPLE/ASF) + TS 103 190-2 §6.2.1.1 (IMS TOC).

Source

pub fn encode_frame_pcm_with_max_sfb( &mut self, frame: &[f32], max_sfb: u32, ) -> Vec<u8>

Encode one IMS v2 mono frame from arbitrary float PCM input (range [-1.0, 1.0]) at a caller-specified max_sfb. Larger values widen the encoder’s frequency coverage at the cost of more bits per frame:

  • max_sfb = 40 → bins 0..508 → ~6.35 kHz @ tl=1920
  • max_sfb = 50 → bins 0..1216 → ~15.2 kHz @ tl=1920
  • max_sfb = 55 → bins 0..1600 → ~20.0 kHz @ tl=1920

max_sfb must satisfy max_sfb <= num_sfb_48(frame_len) (61 at tl=1920). The pad budget scales with max_sfb so the announced audio_size reliably exceeds the actual emission length.

Source

pub fn encode_frame_pcm_stereo( &mut self, frame_l: &[f32], frame_r: &[f32], ) -> Vec<u8>

Encode one IMS v2 stereo frame from arbitrary float PCM input (range [-1.0, 1.0]) for both L and R. Returns the produced frame bytes.

Path A — 2× SCE (split-MDCT) per ETSI TS 103 190-1 §5.3 + §4.2.6.3 Table 22 (stereo_data() with b_enable_mdct_stereo_proc == 0): each channel is encoded independently with the shared forward analysis pipeline (KBD- windowed MDCT, per-band scalefactor, DP-optimal sectioning, HCB1..11 codebook selection, SNF emission). No joint M/S coding.

frame_l / frame_r must each be exactly frame_len samples long (1920 samples for the default 48 kHz / 24 fps configuration). The encoder forces stereo channel mode (channel_mode_value = 0b10) for this call. The decoder’s [crate::asf::parse_stereo_data_body_stateful] split-MDCT path consumes the frame and reconstructs both channels through the shared ASF Huffman pipeline.

max_sfb defaults to 40 (matching the round-48 mono default, covers bins 0..508 ≈ 0..6.35 kHz at tl = 1920) when called via Self::encode_frame_pcm_stereo; use Self::encode_frame_pcm_stereo_with_max_sfb for wider coverage. The decoder’s split-MDCT branch reads BOTH L and R max_sfb with the full n_msfb_bits width (the spec’s b_side_limited only applies to joint-MDCT stereo per §4.3.6.2), so the encoder isn’t limited by the narrower n_side_bits.

Per ETSI TS 103 190-1 §5.3 + §4.2.6.3 + §5.5 (MDCT) + §5.7 / §5.8 (SIMPLE/ASF) + TS 103 190-2 §6.2.1.1 (IMS TOC).

Source

pub fn encode_frame_pcm_stereo_with_max_sfb( &mut self, frame_l: &[f32], frame_r: &[f32], max_sfb: u32, ) -> Vec<u8>

Encode one IMS v2 stereo frame from arbitrary float PCM input (range [-1.0, 1.0]) at a caller-specified max_sfb. Both channels use the same max_sfb — the encoder uses the full n_msfb_bits field width for both. See Self::encode_frame_pcm_stereo.

Round 52 — Path A vs Path B dispatch. The encoder computes the per-SFB average Pearson correlation between the L and R MDCT spectra (via average_per_sfb_correlation) and, when it exceeds Self::STEREO_JOINT_MS_CORRELATION_THRESHOLD (default 0.7), switches to joint M/S CPE (Path B, b_enable_mdct_stereo_proc == 1) per ETSI TS 103 190-1 §5.3 + §4.2.6.3 Table 22 + §7.5 (Pseudocode 77). Otherwise it stays on the round-51 split-MDCT path (Path A, 2× SCE, b_enable_mdct_stereo_proc == 0). Per-SFB M/S vs L/R selection within the joint path is driven by the natural-q bit-cost comparison inside build_stereo_simple_asf_joint_body_from_pcm_spectra.

Use Self::encode_frame_pcm_stereo_split_with_max_sfb or Self::encode_frame_pcm_stereo_joint_with_max_sfb to force a specific path regardless of correlation.

Source

pub fn encode_frame_pcm_stereo_split_with_max_sfb( &mut self, frame_l: &[f32], frame_r: &[f32], max_sfb: u32, ) -> Vec<u8>

Force the split-MDCT (Path A: 2× SCE) encoder path regardless of the L-vs-R correlation. Useful for tests / fixtures that need a deterministic on-wire layout. See Self::encode_frame_pcm_stereo_with_max_sfb.

Source

pub fn encode_frame_pcm_stereo_joint_with_max_sfb( &mut self, frame_l: &[f32], frame_r: &[f32], max_sfb: u32, ) -> Vec<u8>

Force the joint-MDCT (Path B: M/S CPE) encoder path regardless of the L-vs-R correlation. Useful for tests / fixtures that need a deterministic on-wire layout. See Self::encode_frame_pcm_stereo_with_max_sfb.

Source

pub fn encode_frame_pcm_5_0(&mut self, frames: &[&[f32]; 5]) -> Vec<u8>

Encode one IMS v2 5.0 frame from arbitrary float PCM input (range [-1.0, 1.0]) for L, R, C, Ls, Rs.

Path SIMPLE/Cfg3Five — 5 SCE multichannel forward analysis per ETSI TS 103 190-1 §4.2.6.6 Table 25 row case SIMPLE: coding_config == 3 + §4.2.7.5 Table 29 (five_channel_data()): each of the five channels is encoded independently with the shared forward-analysis pipeline (KBD-windowed MDCT, per-band scalefactor, DP-optimal section partition, HCB1..11 codebook selection, SNF emission). One shared sf_info(ASF, 0, 0) precedes the per-channel data; the five_channel_info() uses identity SAP (sap_mode = 0 on every chparam_info(), chel_matsel = 0) so no joint-MDCT mixing happens at decode time — every output channel comes straight from its own sf_data(ASF) body. This is the spec-mandated minimum for the 5.0 SIMPLE path and unblocks the encoder’s path to multichannel.

frames[i] must each be exactly frame_len samples long (1920 samples for the default 48 kHz / 24 fps configuration). The slice order matches the 5.0 output layout (L, R, C, Ls, Rs — Table 180 row coding_config == 3). The encoder forces the 5.0 channel mode (channel_mode_value = 0b1101, 4 b — Table 85 channel_mode 3) for this call.

The decoder’s crate::mch::parse_5x_audio_data_outer for channels == 5 (no LFE) consumes the body, IMDCTs each per-channel spectrum into slots 0..4, and emits 5-channel interleaved S16 PCM at the declared sample rate. There is no companding / ASPX / A-CPL on the SIMPLE path so the round-trip is purely the per-channel MDCT quantisation noise (≥ 20 dB spectral SNR per channel on tone / white-noise fixtures).

max_sfb defaults to 40 (matching the round-49 mono default). Use Self::encode_frame_pcm_5_0_with_max_sfb for wider coverage.

Per ETSI TS 103 190-1 §4.2.6.6 + §4.2.7.5 + §5.5 (MDCT) + §5.7 / §5.8 (SIMPLE/ASF) + TS 103 190-2 §6.2.1.1 (IMS TOC).

Source

pub fn encode_frame_pcm_5_0_with_max_sfb( &mut self, frames: &[&[f32]; 5], max_sfb: u32, ) -> Vec<u8>

Encode one IMS v2 5.0 frame from arbitrary float PCM input at a caller-specified max_sfb. All five channels share the same max_sfb (the joint sf_info header carries one value). See Self::encode_frame_pcm_5_0 for the rest of the contract.

Source

pub fn encode_frame_pcm_5_1(&mut self, frames: &[&[f32]; 6]) -> Vec<u8>

Encode one IMS v2 5.1 frame from float PCM input per ETSI TS 103 190-1 §4.2.6.6 + §4.2.7.5 + TS 103 190-2 §6.2.1.1, building on top of the 5.0 Cfg3Five forward analysis path with an extra LFE mono_data(1) element per Table 25 (if (b_has_lfe) mono_data(1);).

frames is in [L, R, C, Ls, Rs, LFE] order. Each slice must have length frame_len (1920 for the default 48 kHz / 24 fps configuration); panics otherwise.

The encoder forces the 5.1 channel_mode prefix (0b1110, 4 b — Table 85 channel_mode 4) so the decoder’s walk_ac4_substream dispatches channels == 6 through parse_5x_audio_data_outer(b_has_lfe = true). The LFE channel is coded with sf_info_lfe() (Table 35) carrying max_sfb in n_msfbl_bits bits (Table 106 column 4 — 3 bits for tl = 1920 → max_sfb_lfe is capped at 7). The five non-LFE channels share the same Cfg3Five five_channel_data() body as the 5.0 path (identity SAP, independent per-channel SCE).

max_sfb defaults to 40 (matching the round-49 mono / round-74 5.0 default); max_sfb_lfe defaults to 7 (the LFE-spec cap at tl = 1920). Use Self::encode_frame_pcm_5_1_with_max_sfb for wider coverage.

Source

pub fn encode_frame_pcm_5_1_with_max_sfb( &mut self, frames: &[&[f32]; 6], max_sfb: u32, max_sfb_lfe: u32, ) -> Vec<u8>

Encode one IMS v2 5.1 frame from arbitrary float PCM input at caller-specified max_sfb (non-LFE channels) and max_sfb_lfe (LFE channel). See Self::encode_frame_pcm_5_1 for the rest of the contract.

Source

pub fn encode_frame_pcm_7_0(&mut self, frames: &[&[f32]; 7]) -> Vec<u8>

Encode one IMS v2 7.0 (3/4/0) frame from float PCM input per ETSI TS 103 190-1 §4.2.6.14 Table 33 + §4.2.7.5 Table 29 (five_channel_data()) + §4.2.7.4 Table 26 (two_channel_data()). The non-LFE immersive counterpart of Self::encode_frame_pcm_7_1 — same 7_X_codec_mode = SIMPLE + coding_config = Cfg3Five body shape, but the walker’s if (b_has_lfe) mono_data(1); branch is omitted (b_has_lfe = false for channel_mode 5 / 7.0).

frames is in [L, R, C, Ls, Rs, Lb, Rb] order — the inner five_channel_data() (Table 180) carries the front/surround pair L/R/C/Ls/Rs and the SIMPLE/ASPX additional-channel block carries the immersive back pair Lb/Rb via a trailing two_channel_data() per Table 26. The encoder uses identity SAP (b_use_sap_add_ch = 0, sap_mode = 0 on every chparam_info) so no joint-MDCT mixing happens at decode time: every output channel comes straight from its own sf_data(ASF) body.

The encoder forces the 7.0 channel_mode prefix (0b1111000, 7 b — Table 88 channel_mode 5) so the decoder’s walk_ac4_substream dispatches channels == 7 through parse_7x_audio_data_outer(b_has_lfe = false). The five front/surround channels share the same Cfg3Five five_channel_data() body as the 5.0 / 5.1 / 7.1 paths; the additional pair (Lb, Rb) rides the trailing two_channel_data() which the decoder’s dispatch_7x_additional_channel_pair (Table 183 row “3/4/0.x” identity path) routes into output slots 5 / 6.

max_sfb defaults to 40 (matching the round-49 mono / round-74 5.0 / round-80 5.1 / round-91 7.1 default); max_sfb_add defaults to 40 (same width as the 7.0 non-additional channels). Use Self::encode_frame_pcm_7_0_with_max_sfb for wider coverage.

Source

pub fn encode_frame_pcm_7_0_with_max_sfb( &mut self, frames: &[&[f32]; 7], max_sfb: u32, max_sfb_add: u32, ) -> Vec<u8>

Encode one IMS v2 7.0 (3/4/0) frame from arbitrary float PCM input at caller-specified max_sfb (five-channel front/surround SCEs) and max_sfb_add (additional Lb/Rb pair). See Self::encode_frame_pcm_7_0 for the rest of the contract.

Source

pub fn encode_frame_pcm_7_1(&mut self, frames: &[&[f32]; 8]) -> Vec<u8>

Encode one IMS v2 7.1 (3/4/0.1) frame from float PCM input per ETSI TS 103 190-1 §4.2.6.14 Table 33 + §4.2.7.5 Table 29 (five_channel_data()) + §4.2.7.4 Table 26 (two_channel_data()), building on top of the 5.1 Cfg3Five forward analysis path with an extra trailing two_channel_data() for the immersive additional-channel pair (Lb, Rb) per the SIMPLE/ASPX additional-channel block in §4.2.6.14: b_use_sap_add_ch + two_channel_data().

frames is in [L, R, C, Ls, Rs, Lb, Rb, LFE] order (matching the decoder’s output slot convention: slots 0..4 from five_channel_data() per Table 180, slots 5/6 from the additional two_channel_data() per dispatch_7x_additional_channel_pair / Table 183 row “3/4/0.x” identity-SAP path, slot 7 from the LFE mono_data(1)). Each slice must have length frame_len (1920 for the default 48 kHz / 24 fps configuration); panics otherwise.

The encoder forces the 7.1 (3/4/0.1) channel_mode prefix (0b1111001, 7 b — Table 88 channel_mode 6) so the decoder’s walk_ac4_substream dispatches channels == 8 through parse_7x_audio_data_outer(b_has_lfe = true). The LFE channel is coded with sf_info_lfe() (Table 35) carrying max_sfb in n_msfbl_bits bits (Table 106 column 4 — 3 bits for tl = 1920 → max_sfb_lfe is capped at 7). The five non-LFE front/surround channels share the same Cfg3Five five_channel_data() body as the 5.1 path; the additional pair (Lb, Rb) is coded as a single two_channel_data() with identity SAP (b_use_sap_add_ch = 0, sap_mode = 0 on its chparam_info) so no joint-MDCT mixing happens at decode time and slots 5/6 receive Lb/Rb directly.

max_sfb defaults to 40 (matching the round-49 mono / round-74 5.0 / round-80 5.1 default); max_sfb_add defaults to 40 (same width as the 5.1 non-LFE channels); max_sfb_lfe defaults to 7 (the LFE-spec cap at tl = 1920). Use Self::encode_frame_pcm_7_1_with_max_sfb for wider coverage.

Source

pub fn encode_frame_pcm_7_1_with_max_sfb( &mut self, frames: &[&[f32]; 8], max_sfb: u32, max_sfb_add: u32, max_sfb_lfe: u32, ) -> Vec<u8>

Encode one IMS v2 7.1 (3/4/0.1) frame from arbitrary float PCM input at caller-specified max_sfb (five-channel front/surround SCEs), max_sfb_add (additional Lb/Rb pair), and max_sfb_lfe (LFE channel). See Self::encode_frame_pcm_7_1 for the rest of the contract.

Source

pub fn encode_frame_pcm_5_0_acpl3(&mut self, frames: &[&[f32]; 3]) -> Vec<u8>

Encode one IMS v2 5.X frame in 5_X_codec_mode = ASPX_ACPL_3 per ETSI TS 103 190-1 §4.2.6.6 Table 25 row case ASPX_ACPL_3: (round 95). Symmetric counterpart to the decoder’s round-34 crate::mch::parse_5x_audio_data_outer ASPX_ACPL_3 walker.

frames is in [L, R, C] order — three carrier channels. The L/R pair feeds the stereo_data() body (split-MDCT path) and drives the A-CPL Ls/Rs surround reconstruction via Pseudocode 118 at decode time. The centre carrier C is present in the coeffs_per_channel slice but unused on the spec ASPX_ACPL_3 path — the decoder reconstructs the centre from cfg0_centre_mono.scaled_spec (which the ASPX_ACPL_3 walker doesn’t populate), so the decoder’s centre output is zero-filled.

The encoder forces the 5.0 channel_mode prefix (0b1101, 4 b — Table 85 channel_mode 3) so the decoder’s walk_ac4_substream dispatches channels == 5 through parse_5x_audio_data_outer(b_has_lfe = false) with 5_X_codec_mode = AspxAcpl3.

The ASPX/A-CPL parameter bits are emitted as minimum-bit-cost zero-delta Huffman codewords (per round-95 “structural scaffold” mode — see crate::encoder_acpl3). The decoder walks the full Table 25 body and produces 5-channel [L, R, C, Ls, Rs] PCM via crate::acpl_synth::run_acpl_5x_mch_pcm. With all-zero ACPL parameter deltas the surround pair Ls/Rs collapses to the ducker-driven reconstruction from the L/R carriers.

max_sfb defaults to 40 (matching the round-49 mono / round-74 5.0 default).

Source

pub fn encode_frame_pcm_5_1_acpl3(&mut self, frames: &[&[f32]; 4]) -> Vec<u8>

Encode one IMS v2 5.1 frame in 5_X_codec_mode = ASPX_ACPL_3 with an LFE channel per ETSI TS 103 190-1 §4.2.6.6 Table 25 (if (b_has_lfe) mono_data(1);) + §4.2.8 (sf_info_lfe()).

frames is in [L, R, C, LFE] order. The L/R carrier pair drives the stereo body + A-CPL Ls/Rs reconstruction (same as Self::encode_frame_pcm_5_0_acpl3); the LFE channel is coded as a leading mono_data(b_lfe = 1) element per Table 21.

Source

pub fn encode_frame_pcm_5_0_acpl3_real_beta( &mut self, frames: &[&[f32]; 3], beta_scale: f32, ) -> Vec<u8>

Encode one IMS v2 5.0 frame in 5_X_codec_mode = ASPX_ACPL_3 with real per-parameter-band β1 / β2 extraction from the L / R carrier energy distributions (round 193). Symmetric to Self::encode_frame_pcm_5_0_acpl3 but routes the substream body builder through crate::encoder_acpl3::build_5_x_acpl3_body_from_pcm_spectra_real_beta so the β1 / β2 Huffman layers carry the carrier-driven decorrelator gains instead of all-zero codewords.

beta_scale controls the wet/dry balance — see crate::encoder_acpl3::extract_beta_q_per_band_carrier_energy for the magnitude / scale relationship. Values in 0.05..=0.3 produce noticeable surround reconstruction without saturating the BETA codebook.

Source

pub fn encode_frame_pcm_5_1_acpl3_real_beta( &mut self, frames: &[&[f32]; 4], beta_scale: f32, ) -> Vec<u8>

5.1 counterpart to Self::encode_frame_pcm_5_0_acpl3_real_beta. frames is in [L, R, C, LFE] order. The LFE channel is coded as a leading mono_data(b_lfe = 1) element per Table 21 — same path as Self::encode_frame_pcm_5_1_acpl3.

Source

pub fn encode_frame_pcm_5_0_acpl3_real_alpha_beta( &mut self, frames: &[&[f32]; 3], alpha_scale: f32, beta_scale: f32, ) -> Vec<u8>

Encode one IMS v2 5.0 frame in 5_X_codec_mode = ASPX_ACPL_3 with real per-parameter-band α₁ / α₂ extraction from the L↔R carrier cross-correlation (round 196) and the round-193 real β₁ / β₂ extraction from the L / R carrier energies. Symmetric counterpart to Self::encode_frame_pcm_5_0_acpl3_real_beta but routes the substream body builder through crate::encoder_acpl3::build_5_x_acpl3_body_from_pcm_spectra_real_alpha_beta so the α₁ / α₂ Huffman layers carry correlation-driven dry-mix balance indices in addition to the carrier-driven decorrelator gains in β₁ / β₂.

alpha_scale controls the front/back-balance policy — see crate::encoder_acpl3::extract_alpha_q_per_band_carrier_correlation for the magnitude / scale relationship. Values in 0.25..=1.0 produce a noticeable front/back bias on correlated content without saturating the ALPHA codebook.

beta_scale retains its r193 meaning. With alpha_scale = beta_scale = 0.0 the output is byte-identical to Self::encode_frame_pcm_5_0_acpl3’s round-95 scaffold.

Source

pub fn encode_frame_pcm_5_1_acpl3_real_alpha_beta( &mut self, frames: &[&[f32]; 4], alpha_scale: f32, beta_scale: f32, ) -> Vec<u8>

5.1 counterpart to Self::encode_frame_pcm_5_0_acpl3_real_alpha_beta. frames is in [L, R, C, LFE] order. The LFE channel is coded as a leading mono_data(b_lfe = 1) element per Table 21 — same path as Self::encode_frame_pcm_5_1_acpl3.

Source

pub fn encode_frame_pcm_5_0_acpl3_real_alpha_beta_gamma( &mut self, frames: &[&[f32]; 3], alpha_scale: f32, beta_scale: f32, gamma_scale: f32, ) -> Vec<u8>

Encode one IMS v2 5.0 frame in 5_X_codec_mode = ASPX_ACPL_3 with real per-band α + β + γ5/γ6. Layered on top of Self::encode_frame_pcm_5_0_acpl3_real_alpha_beta: the γ5 / γ6 entropy layers now carry per-band magnitudes derived from a 2×2 least-squares fit of the centre channel C ≈ K · (γ5·L + γ6·R) (Pseudocode 118 step 7 + step 11 with K = √2 · (1 + √2) / 2). γ1..γ4 + β3 stay zero-delta.

gamma_scale = 0.0 reproduces the round-196 real-α-β byte stream exactly; gamma_scale = 1.0 writes the full analytic γ pair (clamped to the Table-208 ±2.0 bound). alpha_scale = beta_scale = gamma_scale = 0.0 reproduces the round-95 zero-delta scaffold byte-for-byte.

frames is in [L, R, C] order. The decoder walks the same Table 25 ASPX_ACPL_3 body; γ5 / γ6 feed the ACplModule2 instance that synthesises the centre output channel (Pseudocode 119 with a = 1, b = 0, y = 0). γ1..γ4 still at zero-delta keeps the (L, R, Ls, Rs) sub-pipeline behaviour identical to the round-196 path.

Source

pub fn encode_frame_pcm_5_1_acpl3_real_alpha_beta_gamma( &mut self, frames: &[&[f32]; 4], alpha_scale: f32, beta_scale: f32, gamma_scale: f32, ) -> Vec<u8>

5.1 counterpart to Self::encode_frame_pcm_5_0_acpl3_real_alpha_beta_gamma. frames is in [L, R, C, LFE] order. The LFE channel is coded as a leading mono_data(b_lfe = 1) element per Table 21 — same path as Self::encode_frame_pcm_5_1_acpl3_real_alpha_beta.

Source

pub fn encode_frame_pcm_5_0_acpl3_real_alpha_beta_full_gamma( &mut self, frames: &[&[f32]; 5], alpha_scale: f32, beta_scale: f32, gamma_scale: f32, ) -> Vec<u8>

Encode one IMS v2 5.0 frame in 5_X_codec_mode = ASPX_ACPL_3 with full real per-parameter-band α₁ / α₂ / β₁ / β₂ / γ₁..γ₆ extraction (round 215) — the round-208 entry point Self::encode_frame_pcm_5_0_acpl3_real_alpha_beta_gamma lifted the centre γ₅ / γ₆ pair to real values; this entry point also lifts γ₁ / γ₂ (driving the (L, Ls) pair via Pseudocode 118 step 5) and γ₃ / γ₄ (driving the (R, Rs) pair via Pseudocode 118 step 6), closing the README’s long-standing “γ1..γ4 stay at the round-95 zero-delta scaffold” deferral for the 5_X ACPL_3 path.

The γ₁ / γ₂ pair comes from a per-band 2×2 least-squares fit of the (L, Ls) output sum (L + Ls/√2)/(1 + √2) onto the (L, R) carrier pair; γ₃ / γ₄ come from the symmetric fit on the (R, Rs) pair (see crate::encoder_acpl3::extract_gamma_1_2_q_per_band_surround_least_squares and crate::encoder_acpl3::extract_gamma_3_4_q_per_band_surround_least_squares). Both sums are independent of the α / β decorrelator contributions and equal a (1 + √2) · (γ·L + γ'·R) linear combination, so the resulting 2×2 normal-equations system is identical in shape to the round-208 γ₅ / γ₆ centre fit.

frames is in [L, R, C, Ls, Rs] order. The L / R carriers also feed the round-51 stereo two_channel_data() body the ASPX_ACPL_3 path emits. β₃ stays at the round-95 zero-delta scaffold — its analytic extraction requires a model for the third decorrelator output y₂ which is not observable at encode time. The ASPX envelope layer also stays at the minimum-bit-cost FIXFIX num_env=1 scaffold pending the “real ASPX envelope coding” deferral elsewhere on the README.

alpha_scale / beta_scale / gamma_scale control the extractor magnitude (typically 1.0 for the analytic least-squares solution; 0.0 reproduces the prior-round scaffold byte-for-byte at the corresponding layer position). In particular α/β/γ_scale = 0.0 reproduces the round-95 zero-delta scaffold (Self::encode_frame_pcm_5_0_acpl3) byte-for-byte; γ_scale = 0.0 reproduces the round-196 real-α-β bytes exactly.

Source

pub fn encode_frame_pcm_5_1_acpl3_real_alpha_beta_full_gamma( &mut self, frames: &[&[f32]; 6], alpha_scale: f32, beta_scale: f32, gamma_scale: f32, ) -> Vec<u8>

5.1 counterpart to Self::encode_frame_pcm_5_0_acpl3_real_alpha_beta_full_gamma. frames is in [L, R, C, Ls, Rs, LFE] order. The LFE channel is coded as a leading mono_data(b_lfe = 1) element per Table 21 — same path as Self::encode_frame_pcm_5_1_acpl3_real_alpha_beta_gamma.

Source

pub fn encode_frame_pcm_5_0_acpl3_real_alpha_beta_full_gamma_beta3( &mut self, frames: &[&[f32]; 5], alpha_scale: f32, beta_scale: f32, gamma_scale: f32, beta3_scale: f32, ) -> Vec<u8>

Encode one IMS v2 5.0 frame in 5_X_codec_mode = ASPX_ACPL_3 with real per-parameter-band α₁ / α₂ + β₁ / β₂ + γ₁..γ₆ + β₃ extraction (round 285 — the β₃-real extension of Self::encode_frame_pcm_5_0_acpl3_real_alpha_beta_full_gamma).

frames is in [L, R, C, Ls, Rs] order. β₃ (the gain on the third decorrelator output y₂ per §5.7.7.6.2 Pseudocode 118 steps 8–10) is energy-matched to the centre-channel reconstruction residual left over after the γ₅ / γ₆ dry-mix fit — see crate::encoder_acpl3::extract_beta3_q_per_band_centre_residual. beta3_scale = 0.0 reproduces the round-215 full-γ byte stream exactly; beta3_scale = 1.0 applies the full energy-matching solution clamped to the Table-207 ±1.0 magnitude bound.

Source

pub fn encode_frame_pcm_5_1_acpl3_real_alpha_beta_full_gamma_beta3( &mut self, frames: &[&[f32]; 6], alpha_scale: f32, beta_scale: f32, gamma_scale: f32, beta3_scale: f32, ) -> Vec<u8>

5.1 counterpart to Self::encode_frame_pcm_5_0_acpl3_real_alpha_beta_full_gamma_beta3. frames is in [L, R, C, Ls, Rs, LFE] order. The LFE channel is coded as a leading mono_data(b_lfe = 1) element per Table 21 — same path as Self::encode_frame_pcm_5_1_acpl3_real_alpha_beta_full_gamma.

Source

pub fn encode_frame_pcm_5_0_acpl2(&mut self, frames: &[&[f32]; 3]) -> Vec<u8>

Encode one IMS v2 5.0 frame in 5_X_codec_mode = ASPX_ACPL_2 per ETSI TS 103 190-1 §4.2.6.6 Table 25 row case ASPX_ACPL_2: (round 100). Symmetric counterpart to the decoder’s round-25 crate::mch::parse_5x_audio_data_outer ASPX_ACPL_{1,2} inner- body walker (Pseudocode 117).

frames is in [L, R, C] order — the L/R carrier pair feeds the two_channel_data() body and drives the A-CPL Ls/Rs surround reconstruction via crate::acpl_synth::run_acpl_5x_pair_pcm at decode time; the centre carrier C is coded as a Cfg0 mono_data(0) element. ASPX_ACPL_2 has no surround carriers — the Ls/Rs PCM is reconstructed entirely from the L/R carriers + the two acpl_data_1ch() parameter sets.

The encoder forces the 5.0 channel_mode prefix (0b1101, 4 b — Table 85 channel_mode 3) so the decoder’s walk_ac4_substream dispatches channels == 5 through parse_5x_audio_data_outer(b_has_lfe = false) with 5_X_codec_mode = AspxAcpl2.

The ASPX/A-CPL parameter bits are emitted as minimum-bit-cost zero-delta Huffman codewords (the round-95 “structural scaffold” mode — see crate::encoder_acpl3). The decoder walks the full Table 25 ASPX_ACPL_2 body and produces 5-channel [L, R, C, Ls, Rs] PCM. With all-zero ACPL parameter deltas the surround pair Ls/Rs collapses to the ducker-driven reconstruction from the L/R carriers.

max_sfb defaults to 40 (matching the round-95 ACPL_3 default).

Source

pub fn encode_frame_pcm_5_0_acpl2_with_max_sfb( &mut self, frames: &[&[f32]; 3], max_sfb: u32, ) -> Vec<u8>

max_sfb-parameterised form of Self::encode_frame_pcm_5_0_acpl2.

Source

pub fn encode_frame_pcm_5_0_acpl2_real_alpha_beta( &mut self, frames: &[&[f32]; 5], ) -> Vec<u8>

Encode one IMS v2 frame containing a 5.0 SIMPLE/ASPX_ACPL_2 multichannel substream with real per-parameter-band α + β extraction carried by the two trailing acpl_data_1ch() elements (round 144 — the ACPL_2 5.0 counterpart to the round-132 ACPL_1 5.0 real α + β path).

Per ETSI TS 103 190-1 §5.7.7.5 Pseudocode 116 + §5.7.7.6.1 Pseudocode 117, the A-CPL surround reconstruction carries the level component via α and a decorrelated residual via β:

  α   = 1 − 2·√2 · ⟨x_carrier, x_surround⟩ / ⟨x_carrier, x_carrier⟩
  E[Ls²] = 0.5 · E[L²] · ( (1 − α)² + β² )
  ⇒  β = √max(0, 2·E[Ls²]/E[L²] − (1 − α_dq)²)

Unlike the ACPL_1 paths, ACPL_2 does not transmit the Ls/Rs surround pair on the wire — the decoder reconstructs the surround purely from the L/R carriers + the two acpl_data_1ch() parameter sets. This entry point therefore still emits the round-100 ASPX_ACPL_2 body layout (no joint-MDCT residual layer, no acpl_config_1ch(PARTIAL) qmf_band field), but extracts the α + β indices from the caller’s full 5-channel [L, R, C, Ls, Rs] input rather than pinning them at the zero-codebook scaffold.

frames is in [L, R, C, Ls, Rs] order; β3 / γ stay at the scaffold. The acpl_config_1ch(FULL) carries no qmf_bandstart_band = 0 so every parameter band participates in the α + β coding (in contrast to the ACPL_1 PARTIAL mode whose acpl_qmf_band masks the low bands).

Note (round-128 ALPHA F0 writer-side alpha_q desync — deferred follow-up since round 132). The shared write_acpl_alpha_f0_value writer treats the signed alpha_q ∈ [-N/2..+N/2] returned by quantise_alpha as a raw F0 symbol index without re-centering it against the table’s shortest codeword. The decoder’s dequantize_alpha_index re-centers via lane = alpha_q + N/2, so non-trivial α values do not round-trip bit-exact through the full PCM→MDCT→writer→parser→synth chain when the analytic α resolves to a non-center quantisation lane. The on-wire β codewords for ACPL_2 are wired correctly per §A.3 Table A.40 / A.41 (β uses unsigned-magnitude F0 with cb_off = 0, no re-centering needed); the round-100 zero-α/β scaffold is structurally superseded by this entry point. Once the writer-side desync lands as a follow-up commit the on-wire β recovery will be bit-exact end-to-end.

Source

pub fn encode_frame_pcm_5_0_acpl2_real_alpha_beta_with_max_sfb( &mut self, frames: &[&[f32]; 5], max_sfb: u32, ) -> Vec<u8>

max_sfb-parameterised form of Self::encode_frame_pcm_5_0_acpl2_real_alpha_beta.

Source

pub fn encode_frame_pcm_5_0_acpl1(&mut self, frames: &[&[f32]; 5]) -> Vec<u8>

Encode one IMS v2 frame containing a 5.0 SIMPLE/ASPX_ACPL_1 multichannel substream per ETSI TS 103 190-1 §4.2.6.6 Table 25 row case ASPX_ACPL_1: (Pseudocode 117).

Unlike ASPX_ACPL_2 (which reconstructs the Ls/Rs surround pair purely from the L/R carriers + the two acpl_data_1ch() parameter sets), ASPX_ACPL_1 transmits the surround signal explicitly as a joint-MDCT residual layer (max_sfb_master + 2× chparam_info + 2× sf_data(ASF)) keyed by the acpl_config_1ch(PARTIAL) element’s acpl_qmf_band field. It therefore accepts a full 5-channel [L, R, C, Ls, Rs] input: L/R become the two_channel_data() carriers, C the Cfg0 mono_data(0), and Ls/Rs the residual pair (sSMP,3 / sSMP,4 per Table 181).

The encoder forces the 5.0 channel_mode prefix (0b1101, 4 b — Table 85 channel_mode 3) so the decoder’s walk_ac4_substream dispatches channels == 5 through parse_5x_audio_data_outer(b_has_lfe = false) with 5_X_codec_mode = AspxAcpl1. The ASPX/A-CPL parameter bits use the round-95 minimum-bit-cost zero-delta Huffman scaffold. The decoder walks the full Table 25 ASPX_ACPL_1 body — including the residual layer that IMDCTs into the Ls/Rs PCM carriers — and produces 5-channel [L, R, C, Ls, Rs] PCM via crate::acpl_synth::run_acpl_5x_pair_pcm (Pseudocode 117).

max_sfb defaults to 40; max_sfb_master (the residual-layer band budget) defaults to 20.

Source

pub fn encode_frame_pcm_5_0_acpl1_with_max_sfb( &mut self, frames: &[&[f32]; 5], max_sfb: u32, max_sfb_master: u32, ) -> Vec<u8>

max_sfb / max_sfb_master-parameterised form of Self::encode_frame_pcm_5_0_acpl1.

Source

pub fn encode_frame_pcm_5_0_acpl1_sap( &mut self, frames: &[&[f32]; 5], ) -> Vec<u8>

Encode one IMS v2 frame containing a 5.0 SIMPLE/ASPX_ACPL_1 multichannel substream whose joint-MDCT residual layer is SAP-coded by decision (round 279) — the automatic, decision-driven counterpart of Self::encode_frame_pcm_5_0_acpl1.

Per ETSI TS 103 190-1 §5.3.4.3.2 / Table 181 + §5.3.2 Pseudocode 59, the encoder runs the round-271 crate::asf::select_alpha_q_for_pair least-squares decision per (L, Ls) / (R, Rs) target pair, materialises the SAP-coded chparam_info() rows via crate::asf::build_chparam_info_sap_data_from_alpha_q (falling back to the header-only SapMode::None row when no band benefits), and transmits the Table-181 matrix-input carriers (sSMP_A, sSMP_B) = (M, ·) plus the side prediction residual (sSMP_3, sSMP_4) = (S − g·M, ·) recovered through crate::asf::invert_sap_table_181. For a surround pair correlated with its front carrier the residual sf_data collapses to (near-)silence — the bits the identity path spends on the raw Ls/Rs spectra are saved while the decoder’s apply_sap_table_181 forward mix reproduces the same preliminaries.

On-wire body layout is identical to Self::encode_frame_pcm_5_0_acpl1; when the decision picks no SAP band (e.g. Ls = L) the emitted frame is bit-for-bit identical to the identity-SAP path.

Source

pub fn encode_frame_pcm_5_0_acpl1_sap_with_max_sfb( &mut self, frames: &[&[f32]; 5], max_sfb: u32, max_sfb_master: u32, ) -> Vec<u8>

max_sfb / max_sfb_master-parameterised form of Self::encode_frame_pcm_5_0_acpl1_sap.

Source

pub fn encode_frame_pcm_5_0_acpl1_real_alpha( &mut self, frames: &[&[f32]; 5], ) -> Vec<u8>

Encode one IMS v2 frame containing a 5.0 SIMPLE/ASPX_ACPL_1 multichannel substream with real per-parameter-band α extraction (round 128 — replaces the round-103 zero-delta scaffold for the α coefficient family; β / β3 / γ stay at the scaffold).

Body layout is identical to Self::encode_frame_pcm_5_0_acpl1 (delegates to crate::encoder_acpl3::build_5_x_acpl1_body_from_pcm_spectra_real_alpha); the only on-wire difference is that the two acpl_data_1ch() elements now emit ALPHA F0 + DF codewords with non-zero values chosen to minimise the per-parameter-band residual against the caller’s (Ls, Rs) input vs (L, R) carrier energies. See crate::encoder_acpl3 §“Real per-band α extraction” for the closed-form derivation (β = 0 ⇒ α = 1 − 2·√2·⟨carrier, surround⟩ / ⟨carrier, carrier⟩).

frames is in [L, R, C, Ls, Rs] order. The decoder’s crate::acpl_synth::run_acpl_5x_pair_pcm consumes the recovered α and reconstructs Ls / Rs from the L / R carriers with measurably better fidelity than the zero-α baseline when Ls / Rs aren’t a pure scaled copy of L / R.

Source

pub fn encode_frame_pcm_5_0_acpl1_real_alpha_with_max_sfb( &mut self, frames: &[&[f32]; 5], max_sfb: u32, max_sfb_master: u32, ) -> Vec<u8>

max_sfb / max_sfb_master-parameterised form of Self::encode_frame_pcm_5_0_acpl1_real_alpha.

Source

pub fn encode_frame_pcm_5_0_acpl1_real_alpha_beta( &mut self, frames: &[&[f32]; 5], ) -> Vec<u8>

Encode one IMS v2 frame containing a 5.0 SIMPLE/ASPX_ACPL_1 multichannel substream with real per-parameter-band α + β extraction per ETSI TS 103 190-1 §5.7.7.5 Pseudocode 116 + §5.7.7.6.1 Pseudocode 117 (round 132).

Extends Self::encode_frame_pcm_5_0_acpl1_real_alpha by emitting real per-band β magnitudes alongside the existing real α — the surround Ls/Rs reconstruction at the decoder is no longer a pure level-only image of L/R but also carries the energy of the decorrelated residual:

  E[Ls²] = 0.5 · E[L²] · ( (1 − α)² + β² )

frames is in [L, R, C, Ls, Rs] order; β / γ stay at the round-95 / 100 / 103 / 128 scaffold for non-ACPL_1 paths.

Source

pub fn encode_frame_pcm_5_0_acpl1_real_alpha_beta_with_max_sfb( &mut self, frames: &[&[f32]; 5], max_sfb: u32, max_sfb_master: u32, ) -> Vec<u8>

max_sfb / max_sfb_master-parameterised form of Self::encode_frame_pcm_5_0_acpl1_real_alpha_beta.

Source

pub fn encode_frame_pcm_7_0_acpl2(&mut self, frames: &[&[f32]; 7]) -> Vec<u8>

Encode one IMS v2 frame containing a 7.0 SIMPLE/ASPX_ACPL_2 multichannel substream per ETSI TS 103 190-1 §4.2.6.14 Table 33 row case ASPX_ACPL_2: (round 107). The 7_X (immersive) symmetric counterpart to the round-100 5_X ASPX_ACPL_2 encoder — it reuses the same 1ch ACPL / ASPX parameter shape (Pseudocode 117) but emits the 7_X channel element’s distinct framing (2-bit 7_X_codec_mode, companding_control(5), 2-bit coding_config, two two_channel_data pairs, trailing centre mono_data(0), and the two-aspx_data_2ch envelope trailer).

frames is in [L, R, C, Ls, Rs, Lb, Rb] order — the 7.0 (3/4/0) surface layout. The L/R pair feeds the first two_channel_data() carriers and drives the A-CPL Ls/Rs surround reconstruction via crate::acpl_synth::run_acpl_5x_pair_pcm at decode time. The Ls/Rs pair is coded as the second two_channel_data() (keeps the body well-formed for the walker; the ACPL_2 dispatch reconstructs the surround from L/R + params). The centre C is the trailing Cfg0 mono_data(0). The back pair Lb, Rb is accepted for layout completeness but not carried by the ASPX_ACPL_2 body (the decoder’s ACPL_2 7_X dispatch populates slots 0..4 only — slots 5/6 stay silent), matching the decoder’s documented Table 202 channel mapping.

The encoder forces the 7.0 (3/4/0) channel_mode prefix (0b1111000, 7 b — Table 85 channel_mode 5) so the decoder’s walk_ac4_substream dispatches channels == 7 through parse_7x_audio_data_outer(b_has_lfe = false) with 7_X_codec_mode = AspxAcpl2. The ASPX/A-CPL parameter bits use the round-95 minimum-bit-cost zero-delta Huffman scaffold.

max_sfb defaults to 40.

Source

pub fn encode_frame_pcm_7_0_acpl2_with_max_sfb( &mut self, frames: &[&[f32]; 7], max_sfb: u32, ) -> Vec<u8>

max_sfb-parameterised form of Self::encode_frame_pcm_7_0_acpl2.

Source

pub fn encode_frame_pcm_7_1_acpl2(&mut self, frames: &[&[f32]; 8]) -> Vec<u8>

Encode one IMS v2 frame containing a 7.1 (3/4/0.1) SIMPLE/ASPX_ACPL_2 multichannel substream per ETSI TS 103 190-1 §4.2.6.14 Table 33 row case ASPX_ACPL_2: with b_has_lfe = 1 (round 114). The LFE counterpart of Self::encode_frame_pcm_7_0_acpl2 — it emits the identical 7_X ASPX_ACPL_2 body plus a leading mono_data(b_lfe = 1) element (Table 21 + sf_info_lfe() Table 35) between the I-frame config block and companding_control(5), exactly where the decoder’s parse_7x_audio_data_outer(b_has_lfe = true) reads if (b_has_lfe) mono_data(1);.

frames is in [L, R, C, Ls, Rs, Lb, Rb, LFE] order — the 7.1 (3/4/0.1) surface layout. The L/R pair feeds the first two_channel_data() carriers and drives the A-CPL Ls/Rs surround reconstruction via crate::acpl_synth::run_acpl_5x_pair_pcm at decode time; the Ls/Rs pair rides the second two_channel_data(); the centre C is the trailing Cfg0 mono_data(0); the LFE is the leading mono_data(1). The back pair Lb, Rb is accepted for layout completeness but not carried by the ASPX_ACPL_2 body (the decoder’s 7_X ACPL_2 dispatch populates slots 0..4 + the LFE slot 7 — slots 5/6 stay silent), matching the round-107 documented Table 202 channel mapping plus the round-80 LFE PCM render at decode time.

The encoder forces the 7.1 channel_mode prefix (0b1111001, 7 b — Table 88 channel_mode 6) so the decoder’s walk_ac4_substream dispatches channels == 8 through parse_7x_audio_data_outer(b_has_lfe = true) with 7_X_codec_mode = AspxAcpl2. The ASPX/A-CPL parameter bits use the round-95 minimum-bit-cost zero-delta Huffman scaffold.

max_sfb defaults to 40; max_sfb_lfe defaults to 7 (the LFE-spec cap at tl = 1920, n_msfbl_bits = 3).

Source

pub fn encode_frame_pcm_7_1_acpl2_with_max_sfb( &mut self, frames: &[&[f32]; 8], max_sfb: u32, max_sfb_lfe: u32, ) -> Vec<u8>

max_sfb-parameterised form of Self::encode_frame_pcm_7_1_acpl2. max_sfb governs the five front/surround carrier SCEs and the centre mono; max_sfb_lfe governs the LFE mono_data(1) (clamped to the n_msfbl_bits cap).

Source

pub fn encode_frame_pcm_7_0_acpl2_real_alpha_beta( &mut self, frames: &[&[f32]; 7], ) -> Vec<u8>

Encode one IMS v2 frame containing a 7.0 (3/4/0) SIMPLE/ASPX_ACPL_2 multichannel substream per ETSI TS 103 190-1 §4.2.6.14 Table 33 row case ASPX_ACPL_2: with real per-parameter-band α + β extraction (round 202). The 7_X (immersive) counterpart to the round-144 5.0 ACPL_2 real-α-β path (Self::encode_frame_pcm_5_0_acpl2_real_alpha_beta) and the real-α-β upgrade of the round-107 7.0 ACPL_2 zero-delta path (Self::encode_frame_pcm_7_0_acpl2).

frames is in [L, R, C, Ls, Rs, Lb, Rb] order — the 7.0 (3/4/0) surface layout. The L/R pair feeds the first two_channel_data() carriers and drives the A-CPL Ls/Rs surround reconstruction via crate::acpl_synth::run_acpl_5x_pair_pcm at decode time; the Ls/Rs pair rides the second two_channel_data() and feeds the α + β extractors (D0 module models (L → Ls); D1 module models (R → Rs)). acpl_config_1ch(FULL) carries no qmf_bandstart_band = 0 so every parameter band participates. The centre C is the trailing Cfg0 mono_data(0). The back pair Lb, Rb is accepted for layout completeness but not carried by the ASPX_ACPL_2 body (the decoder’s 7_X ACPL_2 dispatch populates slots 0..4 — slots 5/6 stay silent), matching the round-107 documented Table 202 channel mapping.

The encoder forces the 7.0 channel_mode prefix (0b1111000, 7 b — Table 85 channel_mode 5) so the decoder’s walk_ac4_substream dispatches channels == 7 through parse_7x_audio_data_outer(b_has_lfe = false) with 7_X_codec_mode = AspxAcpl2.

max_sfb defaults to 40.

Source

pub fn encode_frame_pcm_7_0_acpl2_real_alpha_beta_with_max_sfb( &mut self, frames: &[&[f32]; 7], max_sfb: u32, ) -> Vec<u8>

max_sfb-parameterised form of Self::encode_frame_pcm_7_0_acpl2_real_alpha_beta.

Source

pub fn encode_frame_pcm_7_1_acpl2_real_alpha_beta( &mut self, frames: &[&[f32]; 8], ) -> Vec<u8>

Encode one IMS v2 frame containing a 7.1 (3/4/0.1) SIMPLE/ASPX_ACPL_2 multichannel substream per ETSI TS 103 190-1 §4.2.6.14 Table 33 row case ASPX_ACPL_2: with b_has_lfe = 1 and real per-parameter-band α + β extraction (round 202). The LFE counterpart of Self::encode_frame_pcm_7_0_acpl2_real_alpha_beta — it emits the identical 7_X ASPX_ACPL_2 real-α-β body plus a leading mono_data(b_lfe = 1) element between the I-frame config block and companding_control(5), exactly where the decoder’s parse_7x_audio_data_outer(b_has_lfe = true) reads if (b_has_lfe) mono_data(1);.

frames is in [L, R, C, Ls, Rs, Lb, Rb, LFE] order. See Self::encode_frame_pcm_7_0_acpl2_real_alpha_beta for the channel routing contract; the LFE is the leading mono_data(1).

The encoder forces the 7.1 channel_mode prefix (0b1111001, 7 b — Table 88 channel_mode 6) so the decoder dispatches channels == 8 through parse_7x_audio_data_outer(b_has_lfe = true) with 7_X_codec_mode = AspxAcpl2.

max_sfb defaults to 40; max_sfb_lfe defaults to 7 (the LFE-spec cap at tl = 1920, n_msfbl_bits = 3).

Source

pub fn encode_frame_pcm_7_1_acpl2_real_alpha_beta_with_max_sfb( &mut self, frames: &[&[f32]; 8], max_sfb: u32, max_sfb_lfe: u32, ) -> Vec<u8>

max_sfb / max_sfb_lfe-parameterised form of Self::encode_frame_pcm_7_1_acpl2_real_alpha_beta.

Source

pub fn encode_frame_pcm_7_0_acpl1(&mut self, frames: &[&[f32]; 7]) -> Vec<u8>

Encode one IMS v2 frame containing a 7.0 (3/4/0) SIMPLE/ASPX_ACPL_1 multichannel substream per ETSI TS 103 190-1 §4.2.6.14 Table 33 row case ASPX_ACPL_1: (round 118). The 7_X (immersive) counterpart to the round-103 5_X ASPX_ACPL_1 encoder and the encoder side of the decoder’s round-27 parse_7x_audio_data_outer ASPX_ACPL_1 branch.

ASPX_ACPL_1 differs from the round-107 7.0 ASPX_ACPL_2 path in three structural places (the same three that separate the 5_X ACPL_1 path from the 5_X ACPL_2 path): 7_X_codec_mode = 2 (vs 3), acpl_config_1ch is PARTIAL (vs FULL — carries the 3-bit acpl_qmf_band_minus1), and the body carries an explicit joint-MDCT residual layer (max_sfb_master + 2× chparam_info + 2× sf_data(ASF)) transmitting the Ls/Rs surround pair (sSMP,3 / sSMP,4 per Table 181) rather than reconstructing it purely from the L/R carriers.

frames is in [L, R, C, Ls, Rs, Lb, Rb] order — the 7.0 (3/4/0) surface layout. The L/R pair feeds the first two_channel_data() carriers; the Ls/Rs pair rides the second two_channel_data() and the joint-MDCT residual layer; the centre C is the trailing Cfg0 mono_data(0). The back pair Lb, Rb is accepted for layout completeness but not carried by the ASPX_ACPL_1 body (the decoder’s 7_X ACPL_1 dispatch populates slots 0..4 only — slots 5/6 stay silent), matching the round-107 documented Table 202 channel mapping.

The encoder forces the 7.0 (3/4/0) channel_mode prefix (0b1111000, 7 b — Table 85 channel_mode 5) so the decoder’s walk_ac4_substream dispatches channels == 7 through parse_7x_audio_data_outer(b_has_lfe = false) with 7_X_codec_mode = AspxAcpl1. The ASPX/A-CPL parameter bits use the round-95 minimum-bit-cost zero-delta Huffman scaffold.

max_sfb defaults to 40; max_sfb_master (the residual band bound) defaults to 20.

Source

pub fn encode_frame_pcm_7_0_acpl1_with_max_sfb( &mut self, frames: &[&[f32]; 7], max_sfb: u32, max_sfb_master: u32, ) -> Vec<u8>

max_sfb / max_sfb_master-parameterised form of Self::encode_frame_pcm_7_0_acpl1.

Source

pub fn encode_frame_pcm_7_0_acpl1_real_alpha_beta( &mut self, frames: &[&[f32]; 7], ) -> Vec<u8>

Encode one IMS v2 frame containing a 7.0 (3/4/0) SIMPLE/ASPX_ACPL_1 multichannel substream with real per-parameter-band α + β extraction per ETSI TS 103 190-1 §5.7.7.5 Pseudocode 116 + §5.7.7.6.1 Pseudocode 117 (round 135).

The 7_X immersive counterpart of Self::encode_frame_pcm_5_0_acpl1_real_alpha_beta and the real- α+β upgrade of Self::encode_frame_pcm_7_0_acpl1 (which emitted both acpl_data_1ch() sets at the round-118 zero-delta scaffold). The two trailing acpl_data_1ch() parameter sets now carry the analytic α (from the L/Ls and R/Rs MDCT-energy correlation) and the β magnitude that closes the surround/carrier energy balance after α removes the level-only component:

  E[Ls²] = 0.5 · E[L²] · ( (1 − α)² + β² )

frames is in [L, R, C, Ls, Rs, Lb, Rb] order — the 7.0 (3/4/0) surface layout, identical to Self::encode_frame_pcm_7_0_acpl1. β / β3 / γ for non-ACPL_1 paths stay at the scaffold.

Source

pub fn encode_frame_pcm_7_0_acpl1_real_alpha_beta_with_max_sfb( &mut self, frames: &[&[f32]; 7], max_sfb: u32, max_sfb_master: u32, ) -> Vec<u8>

max_sfb / max_sfb_master-parameterised form of Self::encode_frame_pcm_7_0_acpl1_real_alpha_beta.

Source

pub fn encode_frame_pcm_7_1_acpl1(&mut self, frames: &[&[f32]; 8]) -> Vec<u8>

Encode one IMS v2 frame containing a 7.1 (3/4/0.1) SIMPLE/ASPX_ACPL_1 multichannel substream per ETSI TS 103 190-1 §4.2.6.14 Table 33 row case ASPX_ACPL_1: with b_has_lfe = 1 (round 118). The LFE counterpart of Self::encode_frame_pcm_7_0_acpl1 — it emits the identical 7_X ASPX_ACPL_1 body plus a leading mono_data(b_lfe = 1) element (Table 21 + sf_info_lfe() Table 35) between the I-frame config block and companding_control(5), exactly where the decoder’s parse_7x_audio_data_outer(b_has_lfe = true) reads if (b_has_lfe) mono_data(1);.

frames is in [L, R, C, Ls, Rs, Lb, Rb, LFE] order — the 7.1 (3/4/0.1) surface layout. The LFE is the leading mono_data(1); the rest of the body matches the 7.0 ACPL_1 form. The encoder forces the 7.1 channel_mode prefix (0b1111001, 7 b — Table 88 channel_mode 6) so the decoder dispatches channels == 8 through parse_7x_audio_data_outer(b_has_lfe = true) with 7_X_codec_mode = AspxAcpl1; the LFE spectrum IMDCT’s into slot 7 via the round-80 LFE PCM render.

max_sfb defaults to 40; max_sfb_master defaults to 20; max_sfb_lfe defaults to 7 (the LFE-spec cap at tl = 1920, n_msfbl_bits = 3).

Source

pub fn encode_frame_pcm_7_1_acpl1_with_max_sfb( &mut self, frames: &[&[f32]; 8], max_sfb: u32, max_sfb_master: u32, max_sfb_lfe: u32, ) -> Vec<u8>

max_sfb-parameterised form of Self::encode_frame_pcm_7_1_acpl1. max_sfb governs the five front/surround carrier SCEs and the centre mono; max_sfb_master governs the joint-MDCT surround residual layer; max_sfb_lfe governs the LFE mono_data(1) (clamped to the n_msfbl_bits cap).

Source

pub fn encode_frame_pcm_7_1_acpl1_real_alpha_beta( &mut self, frames: &[&[f32]; 8], ) -> Vec<u8>

Encode one IMS v2 frame containing a 7.1 (3/4/0.1) SIMPLE/ASPX_ACPL_1 multichannel substream per ETSI TS 103 190-1 §4.2.6.14 Table 33 row case ASPX_ACPL_1: with b_has_lfe = 1, with real per-parameter-band α + β extraction carried by the two trailing acpl_data_1ch() parameter sets (round 139 — the LFE counterpart of the round-135 7.0 immersive real-α+β path, Self::encode_frame_pcm_7_0_acpl1_real_alpha_beta).

The round-118 7.1 ASPX_ACPL_1 encoder emitted both acpl_data_1ch() parameter sets at the zero-delta scaffold; this entry point upgrades them to carry the analytic α (from the L/Ls and R/Rs MDCT-energy correlation, §5.7.7.5 Pseudocode 116) plus the β magnitude that closes the surround/carrier energy balance after α removes the level-only component (§5.7.7.6.1 Pseudocode 117):

  E[Ls²] = 0.5 · E[L²] · ( (1 − α)² + β² )
  ⇒  β = √max(0, 2·E[Ls²]/E[L²] − (1 − α)²)

frames is in [L, R, C, Ls, Rs, Lb, Rb, LFE] order — the 7.1 (3/4/0.1) surface layout, identical to Self::encode_frame_pcm_7_1_acpl1. The leading mono_data(b_lfe = 1) element (Table 21 + sf_info_lfe() Table 35) is emitted between the I-frame config block and companding_control(5). The on-wire body structure is otherwise identical — decoder resolves SevenXCodecMode::AspxAcpl1 with b_has_lfe = true, both acpl_data_1ch_pair[0/1] populated (now carrying real α + β), joint-MDCT residual layer walked, LFE IMDCT’d into slot 7.

Source

pub fn encode_frame_pcm_7_1_acpl1_real_alpha_beta_with_max_sfb( &mut self, frames: &[&[f32]; 8], max_sfb: u32, max_sfb_master: u32, max_sfb_lfe: u32, ) -> Vec<u8>

max_sfb-parameterised form of Self::encode_frame_pcm_7_1_acpl1_real_alpha_beta. max_sfb governs the five front/surround carrier SCEs and the centre mono; max_sfb_master governs the joint-MDCT surround residual layer; max_sfb_lfe governs the LFE mono_data(1) (clamped to the n_msfbl_bits cap).

Source

pub fn encode_frame_mono_tone_at_hz(&mut self, target_hz: f32) -> (Vec<u8>, f32)

Encode one IMS v2 frame containing a mono SIMPLE/ASF substream whose injected tone falls on the spectral pair nearest the requested frequency. With tl = 1920 at 48 kHz the bin spacing is 12.5 Hz; the chosen pair carries a single non-zero quantised value at the lower bin of that pair.

Returns the encoded frame bytes plus the actual nominal centre frequency the encoder targeted (lower-bin × bin_spacing).

Trait Implementations§

Source§

impl Clone for Ac4ImsEncoder

Source§

fn clone(&self) -> Ac4ImsEncoder

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Ac4ImsEncoder

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Ac4ImsEncoder

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.