mbelib_rs/encode/mod.rs
1// SPDX-FileCopyrightText: 2026 Swift Raccoon
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4//! AMBE 3600×2400 D-STAR encoder (feature-gated).
5//!
6//! Scope: D-STAR only. This encoder produces 72-bit AMBE frames
7//! compatible with the AMBE chips inside real D-STAR radios (DVSI
8//! AMBE-2020 / AMBE-3000 / AMBE-3003). The algorithmic structure is a
9//! Rust port of Max H. Parke's (KA1RBI) `ambe_encoder.cc` from OP25,
10//! which chains Pavel Yazev's IMBE analyzer (OP25 `imbe_vocoder`, 2009,
11//! GPLv3) with AMBE-specific parameter requantization against the
12//! szechyjs mbelib codebooks we already ship in [`crate::tables`].
13//!
14//! # Phase status
15//!
16//! | Phase | Adds | Status |
17//! |------:|------|--------|
18//! | P1 | bit pack + interleave + C1 XOR ([`pack_frame`]) | done |
19//! | P2 | DC removal, LPF, window, FFT ([`analyze_frame`]) | done |
20//! | P3 | pitch estimation (sub-harmonic summation port of `pitch_est.cc`) | done (single-frame; multi-frame DP deferred) |
21//! | P4 | V/UV + spectral amplitudes + gain quantization ([`detect_vuv`], [`extract_spectral_amplitudes`], `quantize`) | done |
22//! | P5 | PRBA/HOC codebook search, FEC, `AmbeEncoder` wrapper | done (bit-exact vs OP25 on b3..b7) |
23//! | P6 | chip-interop tuning | partial (see [`encoder`]'s status block) |
24//!
25//! The top-level entry point is [`AmbeEncoder::encode_frame`]. The
26//! individual stage functions (`analyze_frame`, `PitchTracker`,
27//! `detect_vuv`, `extract_spectral_amplitudes`) remain public so
28//! diagnostic tooling (`examples/validate_*.rs`) can feed known-good
29//! inputs at each stage boundary.
30//!
31//! # IP status
32//!
33//! All patents on the D-STAR AMBE 3600×2400 variant expired in 2017.
34//! The later AMBE+2 "half-rate" variant (DMR / YSF / NXDN) remains
35//! covered by US 8,359,197 B2 (DVSI, active until 2028-05-20). This
36//! module deliberately does **not** implement AMBE+2; a `set_49bit_mode`
37//! equivalent is explicitly out of scope.
38
39mod analyze;
40#[cfg(not(feature = "kenwood-tables"))]
41mod dc_rmv;
42mod encoder;
43mod interleave;
44mod pack;
45mod pe_lpf;
46mod pitch;
47mod pitch_quant;
48mod quantize;
49mod spectral;
50mod state;
51mod vuv;
52mod window;
53mod wr_sp;
54
55#[cfg(feature = "kenwood-tables")]
56pub mod kenwood;
57
58pub use analyze::{FftPlan, analyze_frame};
59pub use encoder::AmbeEncoder;
60pub use pack::pack_frame;
61pub use pitch::{PitchEstimate, PitchTracker, compute_e_p};
62pub use spectral::{MAX_HARMONICS, SpectralAmplitudes, extract_spectral_amplitudes};
63pub use state::EncoderBuffers;
64pub use vuv::{MAX_BANDS, VuvDecisions, VuvState, detect_vuv, detect_vuv_and_sa};
65
66/// Validation-only exposure of the internal quantize pipeline.
67///
68/// External diagnostic tools can feed known-good OP25 reference
69/// inputs into [`validation::quantize`] and compare the resulting
70/// `b[0..8]` bit assignments against OP25's dumped values. This is
71/// how the April 2026 stage-by-stage investigation against the
72/// reference implementation was performed.
73pub mod validation {
74 pub use super::quantize::{PrevFrameState, QuantizeOutcome, quantize};
75}