audio_codec/
g722.rs

1use super::{Decoder, Encoder, PcmBuf, Sample};
2
3pub enum Bitrate {
4    Mode1_64000,
5    Mode2_56000,
6    Mode3_48000,
7}
8
9// Quantization decision thresholds used in the encoder
10const QUANT_DECISION_LEVEL: [i32; 32] = [
11    0, 35, 72, 110, 150, 190, 233, 276, 323, 370, 422, 473, 530, 587, 650, 714, 786, 858, 940,
12    1023, 1121, 1219, 1339, 1458, 1612, 1765, 1980, 2195, 2557, 2919, 0, 0,
13];
14
15// Negative quantization interval indices
16const QUANT_INDEX_NEG: [i32; 32] = [
17    0, 63, 62, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
18    10, 9, 8, 7, 6, 5, 4, 0,
19];
20
21// Positive quantization interval indices
22const QUANT_INDEX_POS: [i32; 32] = [
23    0, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39,
24    38, 37, 36, 35, 34, 33, 32, 0,
25];
26
27// Scale factor adaptation table for low band
28const SCALE_FACTOR_ADJUST_LOW: [i32; 8] = [-60, -30, 58, 172, 334, 538, 1198, 3042];
29
30// Mapping from 4 bits of low band code to 3 bits of logarithmic scale factor
31const LOG_SCALE_FACTOR_MAP: [i32; 16] = [0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0];
32
33// Inverse logarithmic base for computing the scale factor
34const INV_LOG_BASE: [i32; 32] = [
35    2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383, 2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834,
36    2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371, 3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008,
37];
38
39// Quantizer multipliers for 4-bit low band
40const QUANT_MULT_LOW_4BIT: [i32; 16] = [
41    0, -20456, -12896, -8968, -6288, -4240, -2584, -1200, 20456, 12896, 8968, 6288, 4240, 2584,
42    1200, 0,
43];
44
45// Quantizer multipliers for 2-bit high band
46const QUANT_MULT_HIGH_2BIT: [i32; 4] = [-7408, -1616, 7408, 1616];
47
48// QMF filter coefficients for band splitting and reconstruction
49const QMF_FILTER_COEFS: [i32; 12] = [3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11];
50
51// Negative high band quantization indices
52const HIGH_QUANT_INDEX_NEG: [i32; 3] = [0, 1, 0];
53
54// Positive high band quantization indices
55const HIGH_QUANT_INDEX_POS: [i32; 3] = [0, 3, 2];
56
57// Scale factor adaptation table for high band
58const SCALE_FACTOR_ADJUST_HIGH: [i32; 3] = [0, -214, 798];
59
60// Mapping from 2 bits of high band code to 2 bits of logarithmic scale factor
61const HIGH_LOG_SCALE_MAP: [i32; 4] = [2, 1, 2, 1];
62
63// Quantizer multipliers for 5-bit quantization (56kbps mode)
64const QUANT_MULT_56K: [i32; 32] = [
65    -280, -280, -23352, -17560, -14120, -11664, -9752, -8184, -6864, -5712, -4696, -3784, -2960,
66    -2208, -1520, -880, 23352, 17560, 14120, 11664, 9752, 8184, 6864, 5712, 4696, 3784, 2960, 2208,
67    1520, 880, 280, -280,
68];
69
70// Quantizer multipliers for 6-bit quantization (64kbps mode)
71const QUANT_MULT_64K: [i32; 64] = [
72    -136, -136, -136, -136, -24808, -21904, -19008, -16704, -14984, -13512, -12280, -11192, -10232,
73    -9360, -8576, -7856, -7192, -6576, -6000, -5456, -4944, -4464, -4008, -3576, -3168, -2776,
74    -2400, -2032, -1688, -1360, -1040, -728, 24808, 21904, 19008, 16704, 14984, 13512, 12280,
75    11192, 10232, 9360, 8576, 7856, 7192, 6576, 6000, 5456, 4944, 4464, 4008, 3576, 3168, 2776,
76    2400, 2032, 1688, 1360, 1040, 728, 432, 136, -432, -136,
77];
78
79impl Bitrate {
80    fn bits_per_sample(&self) -> i32 {
81        match self {
82            Bitrate::Mode1_64000 => 8,
83            Bitrate::Mode2_56000 => 7,
84            Bitrate::Mode3_48000 => 6,
85        }
86    }
87}
88
89/// G.722 ADPCM band state structure used in the codec
90/// Each band (lower and upper) uses an independent state structure
91#[derive(Default)]
92struct G722Band {
93    /// Current signal prediction value (signal estimate)
94    signal_estimate: i32,
95    /// Pole filter output (result from IIR filter part)
96    pole_filter_output: i32,
97    /// Zero filter output (result from FIR filter part)
98    zero_filter_output: i32,
99    /// Reconstructed signal history [current, previous, previous-1]
100    reconstructed_signal: [i32; 3],
101    /// Pole filter coefficients [unused(0), a1, a2]
102    pole_coefficients: [i32; 3],
103    /// Temporary pole filter coefficients [unused(0), a1', a2']
104    pole_coefficients_temp: [i32; 3],
105    /// Partially reconstructed signal history [current, previous, previous-1]
106    partial_reconstructed: [i32; 3],
107    /// Difference signal history [current, previous, ..., previous-5]
108    difference_signal: [i32; 7],
109    /// Zero filter coefficients [unused(0), b1, b2, ..., b6]
110    zero_coefficients: [i32; 7],
111    /// Temporary zero filter coefficients [unused(0), b1', b2', ..., b6']
112    zero_coefficients_temp: [i32; 7],
113    /// Log scale factor (used for quantization and dequantization)
114    log_scale_factor: i32,
115    /// Quantizer step size (used for adaptive quantization)
116    quantizer_step_size: i32,
117}
118
119#[inline(always)]
120fn saturate(amp: i32) -> i32 {
121    amp.clamp(i16::MIN as i32, i16::MAX as i32)
122}
123
124/// Process Block 4 operations for G.722 ADPCM algorithm
125/// This function performs the predictor adaptation and reconstruction steps
126/// as defined in the G.722 standard
127#[inline]
128fn block4(band: &mut G722Band, d: i32) {
129    // Block 4, RECONS - Reconstruct the signal
130    band.difference_signal[0] = d;
131    band.reconstructed_signal[0] = saturate(band.signal_estimate + d);
132
133    // Block 4, PARREC - Partial reconstruction
134    let partial_rec0 = saturate(band.zero_filter_output + d);
135    band.partial_reconstructed[0] = partial_rec0;
136
137    // Block 4, UPPOL2 - Update second predictor coefficient
138    let s0 = partial_rec0 >> 15;
139    let s1 = band.partial_reconstructed[1] >> 15;
140    let s2 = band.partial_reconstructed[2] >> 15;
141
142    let a1_scaled = saturate(band.pole_coefficients[1] << 2);
143
144    let mut a2_update = if s0 == s1 { -a1_scaled } else { a1_scaled };
145    a2_update = a2_update.min(32767);
146
147    let mut a2_adj = a2_update >> 7;
148    a2_adj += if s0 == s2 { 128 } else { -128 };
149    a2_adj += (band.pole_coefficients[2] * 32512) >> 15;
150
151    band.pole_coefficients_temp[2] = a2_adj.clamp(-12288, 12288);
152
153    // Block 4, UPPOL1 - Update first predictor coefficient
154    let sign_factor = if s0 == s1 { 192 } else { -192 };
155    let leakage = (band.pole_coefficients[1] * 32640) >> 15;
156    band.pole_coefficients_temp[1] = saturate(sign_factor + leakage);
157
158    let limit = saturate(15360 - band.pole_coefficients_temp[2]);
159    band.pole_coefficients_temp[1] = band.pole_coefficients_temp[1].clamp(-limit, limit);
160
161    // Block 4, UPZERO - Update zero section (FIR) coefficients
162    let step_size = if d == 0 { 0 } else { 128 };
163    let sd = d >> 15;
164
165    {
166        macro_rules! update_zero {
167            ($i:expr) => {
168                let sz = band.difference_signal[$i] >> 15;
169                let adj = if sz == sd { step_size } else { -step_size };
170                let leakage = (band.zero_coefficients[$i] * 32640) >> 15;
171                band.zero_coefficients_temp[$i] = saturate(adj + leakage);
172            };
173        }
174        update_zero!(1);
175        update_zero!(2);
176        update_zero!(3);
177        update_zero!(4);
178        update_zero!(5);
179        update_zero!(6);
180    }
181
182    // Block 4, DELAYA - Delay updates for filter memory
183    band.difference_signal[6] = band.difference_signal[5];
184    band.difference_signal[5] = band.difference_signal[4];
185    band.difference_signal[4] = band.difference_signal[3];
186    band.difference_signal[3] = band.difference_signal[2];
187    band.difference_signal[2] = band.difference_signal[1];
188    band.difference_signal[1] = d;
189
190    band.zero_coefficients[1] = band.zero_coefficients_temp[1];
191    band.zero_coefficients[2] = band.zero_coefficients_temp[2];
192    band.zero_coefficients[3] = band.zero_coefficients_temp[3];
193    band.zero_coefficients[4] = band.zero_coefficients_temp[4];
194    band.zero_coefficients[5] = band.zero_coefficients_temp[5];
195    band.zero_coefficients[6] = band.zero_coefficients_temp[6];
196
197    band.reconstructed_signal[2] = band.reconstructed_signal[1];
198    band.reconstructed_signal[1] = band.reconstructed_signal[0];
199    band.partial_reconstructed[2] = band.partial_reconstructed[1];
200    band.partial_reconstructed[1] = partial_rec0;
201
202    band.pole_coefficients[1] = band.pole_coefficients_temp[1];
203    band.pole_coefficients[2] = band.pole_coefficients_temp[2];
204
205    // Block 4, FILTEP - Pole section (IIR) filtering
206    let r1_adj = saturate(band.reconstructed_signal[1] << 1);
207    let pole1 = (band.pole_coefficients[1] * r1_adj) >> 15;
208
209    let r2_adj = saturate(band.reconstructed_signal[2] << 1);
210    let pole2 = (band.pole_coefficients[2] * r2_adj) >> 15;
211
212    band.pole_filter_output = saturate(pole1 + pole2);
213
214    // Block 4, FILTEZ - Zero section (FIR) filtering
215    let mut zero_out = (band.zero_coefficients[1] * saturate(band.difference_signal[1] << 1)) >> 15;
216    zero_out += (band.zero_coefficients[2] * saturate(band.difference_signal[2] << 1)) >> 15;
217    zero_out += (band.zero_coefficients[3] * saturate(band.difference_signal[3] << 1)) >> 15;
218    zero_out += (band.zero_coefficients[4] * saturate(band.difference_signal[4] << 1)) >> 15;
219    zero_out += (band.zero_coefficients[5] * saturate(band.difference_signal[5] << 1)) >> 15;
220    zero_out += (band.zero_coefficients[6] * saturate(band.difference_signal[6] << 1)) >> 15;
221
222    band.zero_filter_output = saturate(zero_out);
223
224    // Block 4, PREDIC - Prediction
225    band.signal_estimate = saturate(band.pole_filter_output + band.zero_filter_output);
226}
227
228pub struct G722Encoder {
229    packed: bool,
230    eight_k: bool,
231    bits_per_sample: i32,
232    x: [i32; 24],
233    band: [G722Band; 2],
234    out_buffer: u32,
235    out_bits: i32,
236}
237
238pub struct G722Decoder {
239    packed: bool,
240    eight_k: bool,
241    bits_per_sample: i32,
242    x: [i32; 24],
243    band: [G722Band; 2],
244    in_buffer: u32,
245    in_bits: i32,
246}
247
248impl G722Encoder {
249    pub fn new() -> Self {
250        Self::with_options(Bitrate::Mode1_64000, false, false)
251    }
252
253    /// Creates an encoder with specified bitrate and options
254    pub fn with_options(rate: Bitrate, eight_k: bool, packed: bool) -> Self {
255        let mut encoder = Self {
256            packed,
257            eight_k,
258            bits_per_sample: rate.bits_per_sample(),
259            x: [0; 24],
260            band: [G722Band::default(), G722Band::default()],
261            out_buffer: 0,
262            out_bits: 0,
263        };
264
265        // Initialize band states with correct starting values
266        encoder.band[0].log_scale_factor = 32 << 2; // Initial det value for lower band
267        encoder.band[1].log_scale_factor = 8 << 2; // Initial det value for upper band
268
269        encoder
270    }
271
272    /// Encode 16-bit PCM samples into G.722 format
273    /// This function follows the G.722 standard algorithm exactly
274    fn g722_encode(&mut self, amp: &[i16]) -> Vec<u8> {
275        // Pre-allocate output buffer with appropriate capacity
276        let mut output = Vec::with_capacity(amp.len() / 2 + 1);
277
278        // Initialize processing variables
279        let mut input_idx = 0;
280
281        if self.eight_k {
282            while input_idx < amp.len() {
283                // 8kHz mode - Just use input directly with scaling
284                let xlow = amp[input_idx] as i32 >> 1;
285                input_idx += 1;
286
287                // 8kHz mode - only low band matters
288                let code = self.encode_low_band(xlow, true);
289                self.output_code(code, &mut output);
290            }
291        } else {
292            // Process all input samples in 16kHz mode
293            // Use chunks_exact(2) for better performance and to avoid bound checks
294            let chunks = amp.chunks_exact(2);
295            let rem = chunks.remainder();
296
297            for chunk in chunks {
298                // Shuffle buffer down to make room for new samples
299                self.x.copy_within(2..24, 0);
300
301                // Add new samples to buffer
302                self.x[22] = chunk[0] as i32;
303                self.x[23] = chunk[1] as i32;
304
305                // Apply QMF filter to split input into bands
306                // Unrolled loop for 12 coefficients
307                let mut sumodd = self.x[0] * QMF_FILTER_COEFS[0];
308                sumodd += self.x[2] * QMF_FILTER_COEFS[1];
309                sumodd += self.x[4] * QMF_FILTER_COEFS[2];
310                sumodd += self.x[6] * QMF_FILTER_COEFS[3];
311                sumodd += self.x[8] * QMF_FILTER_COEFS[4];
312                sumodd += self.x[10] * QMF_FILTER_COEFS[5];
313                sumodd += self.x[12] * QMF_FILTER_COEFS[6];
314                sumodd += self.x[14] * QMF_FILTER_COEFS[7];
315                sumodd += self.x[16] * QMF_FILTER_COEFS[8];
316                sumodd += self.x[18] * QMF_FILTER_COEFS[9];
317                sumodd += self.x[20] * QMF_FILTER_COEFS[10];
318                sumodd += self.x[22] * QMF_FILTER_COEFS[11];
319
320                let mut sumeven = self.x[1] * QMF_FILTER_COEFS[11];
321                sumeven += self.x[3] * QMF_FILTER_COEFS[10];
322                sumeven += self.x[5] * QMF_FILTER_COEFS[9];
323                sumeven += self.x[7] * QMF_FILTER_COEFS[8];
324                sumeven += self.x[9] * QMF_FILTER_COEFS[7];
325                sumeven += self.x[11] * QMF_FILTER_COEFS[6];
326                sumeven += self.x[13] * QMF_FILTER_COEFS[5];
327                sumeven += self.x[15] * QMF_FILTER_COEFS[4];
328                sumeven += self.x[17] * QMF_FILTER_COEFS[3];
329                sumeven += self.x[19] * QMF_FILTER_COEFS[2];
330                sumeven += self.x[21] * QMF_FILTER_COEFS[1];
331                sumeven += self.x[23] * QMF_FILTER_COEFS[0];
332
333                // Scale filter outputs to get low and high bands
334                let xlow = (sumeven + sumodd) >> 14;
335                let xhigh = (sumeven - sumodd) >> 14;
336
337                // 16kHz mode - encode both bands
338                let ilow = self.encode_low_band(xlow, false);
339                let ihigh = self.encode_high_band(xhigh);
340                let code = (ihigh << 6 | ilow) >> (8 - self.bits_per_sample);
341
342                // Output the encoded code
343                self.output_code(code, &mut output);
344            }
345
346            if !rem.is_empty() {
347                self.x.copy_within(2..24, 0);
348                self.x[22] = rem[0] as i32;
349                self.x[23] = 0;
350                let mut sumodd = self.x[0] * QMF_FILTER_COEFS[0];
351                sumodd += self.x[2] * QMF_FILTER_COEFS[1];
352                sumodd += self.x[4] * QMF_FILTER_COEFS[2];
353                sumodd += self.x[6] * QMF_FILTER_COEFS[3];
354                sumodd += self.x[8] * QMF_FILTER_COEFS[4];
355                sumodd += self.x[10] * QMF_FILTER_COEFS[5];
356                sumodd += self.x[12] * QMF_FILTER_COEFS[6];
357                sumodd += self.x[14] * QMF_FILTER_COEFS[7];
358                sumodd += self.x[16] * QMF_FILTER_COEFS[8];
359                sumodd += self.x[18] * QMF_FILTER_COEFS[9];
360                sumodd += self.x[20] * QMF_FILTER_COEFS[10];
361                sumodd += self.x[22] * QMF_FILTER_COEFS[11];
362
363                let mut sumeven = self.x[1] * QMF_FILTER_COEFS[11];
364                sumeven += self.x[3] * QMF_FILTER_COEFS[10];
365                sumeven += self.x[5] * QMF_FILTER_COEFS[9];
366                sumeven += self.x[7] * QMF_FILTER_COEFS[8];
367                sumeven += self.x[9] * QMF_FILTER_COEFS[7];
368                sumeven += self.x[11] * QMF_FILTER_COEFS[6];
369                sumeven += self.x[13] * QMF_FILTER_COEFS[5];
370                sumeven += self.x[15] * QMF_FILTER_COEFS[4];
371                sumeven += self.x[17] * QMF_FILTER_COEFS[3];
372                sumeven += self.x[19] * QMF_FILTER_COEFS[2];
373                sumeven += self.x[21] * QMF_FILTER_COEFS[1];
374                sumeven += self.x[23] * QMF_FILTER_COEFS[0];
375
376                let xlow = (sumeven + sumodd) >> 14;
377                let xhigh = (sumeven - sumodd) >> 14;
378                let ilow = self.encode_low_band(xlow, false);
379                let ihigh = self.encode_high_band(xhigh);
380                let code = (ihigh << 6 | ilow) >> (8 - self.bits_per_sample);
381                self.output_code(code, &mut output);
382            }
383        }
384
385        // Handle any remaining bits in the output buffer
386        if self.packed && self.out_bits > 0 {
387            output.push((self.out_buffer & 0xFF) as u8);
388        }
389
390        output
391    }
392
393    /// Encode low band sample and update state
394    /// Returns the encoded low band bits
395    #[inline]
396    fn encode_low_band(&mut self, xlow: i32, is_eight_k: bool) -> i32 {
397        // Block 1L, SUBTRA - Calculate difference signal
398        let el = saturate(xlow - self.band[0].signal_estimate);
399
400        // Block 1L, QUANTL - Quantize difference signal
401        let wd = el.abs().wrapping_sub((el >> 31) & 1);
402
403        // Find quantization interval using linear search (more predictable for audio)
404        let lsf = self.band[0].log_scale_factor;
405        let mut quantization_idx = 1;
406        while quantization_idx < 30 {
407            let decision_level = (QUANT_DECISION_LEVEL[quantization_idx] * lsf) >> 12;
408            if wd < decision_level {
409                break;
410            }
411            quantization_idx += 1;
412        }
413
414        // Select output bits based on sign
415        let ilow = if el < 0 {
416            QUANT_INDEX_NEG[quantization_idx]
417        } else {
418            QUANT_INDEX_POS[quantization_idx]
419        };
420
421        // Block 2L, INVQAL - Inverse quantize for prediction
422        let ril = ilow >> 2;
423        let wd2 = QUANT_MULT_LOW_4BIT[ril as usize];
424        let dlow = (self.band[0].log_scale_factor * wd2) >> 15;
425
426        // Block 3L, LOGSCL - Update scale factor
427        let il4 = LOG_SCALE_FACTOR_MAP[ril as usize];
428        let mut nb = (self.band[0].quantizer_step_size * 127) >> 7;
429        nb += SCALE_FACTOR_ADJUST_LOW[il4 as usize];
430        self.band[0].quantizer_step_size = nb.clamp(0, 18432);
431
432        // Block 3L, SCALEL - Compute new quantizer scale factor
433        let wd1 = self.band[0].quantizer_step_size >> 6 & 31;
434        let wd2 = 8 - (self.band[0].quantizer_step_size >> 11);
435        let wd3 = if wd2 < 0 {
436            INV_LOG_BASE[wd1 as usize] << -wd2
437        } else {
438            INV_LOG_BASE[wd1 as usize] >> wd2
439        };
440        self.band[0].log_scale_factor = wd3 << 2;
441
442        // Apply predictor adaptation (ADPCM core algorithm)
443        block4(&mut self.band[0], dlow);
444
445        // Return appropriate value based on mode
446        if is_eight_k {
447            ((0xc0 | ilow) >> 8) - self.bits_per_sample
448        } else {
449            ilow
450        }
451    }
452
453    /// Encode high band sample and update state
454    /// Returns the encoded high band bits
455    #[inline]
456    fn encode_high_band(&mut self, xhigh: i32) -> i32 {
457        // Block 1H, SUBTRA - Calculate difference signal
458        let eh = saturate(xhigh - self.band[1].signal_estimate);
459
460        // Block 1H, QUANTH - Quantize difference signal
461        let wd = if eh >= 0 { eh } else { -(eh + 1) };
462        let decision_level = (564 * self.band[1].log_scale_factor) >> 12;
463
464        // Determine quantization level for high band (2-bit)
465        let mih = if wd >= decision_level { 2 } else { 1 };
466        let ihigh = if eh < 0 {
467            HIGH_QUANT_INDEX_NEG[mih as usize]
468        } else {
469            HIGH_QUANT_INDEX_POS[mih as usize]
470        };
471
472        // Block 2H, INVQAH - Inverse quantize for prediction
473        let wd2 = QUANT_MULT_HIGH_2BIT[ihigh as usize];
474        let dhigh = (self.band[1].log_scale_factor * wd2) >> 15;
475
476        // Block 3H, LOGSCH - Update scale factor
477        let ih2 = HIGH_LOG_SCALE_MAP[ihigh as usize];
478        let mut nb = (self.band[1].quantizer_step_size * 127) >> 7;
479        nb += SCALE_FACTOR_ADJUST_HIGH[ih2 as usize];
480        self.band[1].quantizer_step_size = nb.clamp(0, 22528);
481
482        // Block 3H, SCALEH - Compute quantizer scale factor
483        let wd1 = self.band[1].quantizer_step_size >> 6 & 31;
484        let wd2 = 10 - (self.band[1].quantizer_step_size >> 11);
485        let wd3 = if wd2 < 0 {
486            INV_LOG_BASE[wd1 as usize] << -wd2
487        } else {
488            INV_LOG_BASE[wd1 as usize] >> wd2
489        };
490        self.band[1].log_scale_factor = wd3 << 2;
491
492        // Apply predictor adaptation (ADPCM core algorithm)
493        block4(&mut self.band[1], dhigh);
494
495        ihigh
496    }
497
498    /// Add encoded bits to the output buffer
499    fn output_code(&mut self, code: i32, output: &mut Vec<u8>) {
500        if self.packed {
501            // Pack the code bits across byte boundaries
502            self.out_buffer |= (code as u32) << self.out_bits;
503            self.out_bits += self.bits_per_sample;
504
505            // When we have at least 8 bits, output a byte
506            if self.out_bits >= 8 {
507                output.push((self.out_buffer & 0xFF) as u8);
508                self.out_bits -= 8;
509                self.out_buffer >>= 8;
510            }
511        } else {
512            // Direct byte-aligned output
513            output.push(code as u8);
514        }
515    }
516}
517
518impl G722Decoder {
519    pub fn new() -> Self {
520        Self::with_options(Bitrate::Mode1_64000, false, false)
521    }
522
523    pub fn with_options(rate: Bitrate, packed: bool, eight_k: bool) -> Self {
524        Self {
525            packed,
526            eight_k,
527            bits_per_sample: rate.bits_per_sample(),
528            x: Default::default(),
529            band: Default::default(),
530            in_buffer: 0,
531            in_bits: 0,
532        }
533    }
534
535    /// Extracts the next G.722 code from the input data stream
536    #[inline]
537    fn extract_code(&mut self, data: &[u8], idx: &mut usize) -> i32 {
538        if self.packed {
539            // When packed, bits are combined across bytes
540            if self.in_bits < self.bits_per_sample {
541                self.in_buffer |= (data[*idx] as u32) << self.in_bits;
542                *idx += 1;
543                self.in_bits += 8;
544            }
545            let code = (self.in_buffer & ((1 << self.bits_per_sample) - 1) as u32) as i32;
546            self.in_buffer >>= self.bits_per_sample;
547            self.in_bits -= self.bits_per_sample;
548            code
549        } else {
550            // Direct byte-based access when not packed
551            let code = data[*idx] as i32;
552            *idx += 1;
553            code
554        }
555    }
556
557    /// Parses the G.722 code into low-band word and high-band index based on bit rate
558    #[inline]
559    fn parse_code(&self, code: i32) -> (i32, i32, i32) {
560        // Returns (wd1, ihigh, wd2) tuple: low-band word, high-band index, and scaled value
561        match self.bits_per_sample {
562            7 => {
563                // 56 kbit/s mode
564                let wd1 = code & 0x1f;
565                let ihigh = (code >> 5) & 0x3;
566                let wd2 = QUANT_MULT_56K[wd1 as usize];
567                (wd1 >> 1, ihigh, wd2)
568            }
569            6 => {
570                // 48 kbit/s mode
571                let wd1 = code & 0xf;
572                let ihigh = (code >> 4) & 0x3;
573                let wd2 = QUANT_MULT_LOW_4BIT[wd1 as usize];
574                (wd1, ihigh, wd2)
575            }
576            _ => {
577                // 64 kbit/s mode (default)
578                let wd1 = code & 0x3f;
579                let ihigh = (code >> 6) & 0x3;
580                let wd2 = QUANT_MULT_64K[wd1 as usize];
581                (wd1 >> 2, ihigh, wd2)
582            }
583        }
584    }
585
586    /// Process the low band component of the G.722 stream
587    #[inline]
588    fn process_low_band(&mut self, wd1: i32, wd2: i32) -> i32 {
589        // Block 5L, LOW BAND INVQBL - Inverse quantization for low band
590        let dequant = (self.band[0].log_scale_factor * wd2) >> 15;
591
592        // Block 5L, RECONS - Reconstruction of low band signal
593        let rlow = self.band[0].signal_estimate + dequant;
594
595        // Block 6L, LIMIT - Limiting to valid range
596        let rlow = rlow.clamp(-16384, 16383);
597
598        // Block 2L, INVQAL - Inverse adaptive quantizer for prediction
599        let wd2 = QUANT_MULT_LOW_4BIT[wd1 as usize];
600        let dlowt = (self.band[0].log_scale_factor * wd2) >> 15;
601
602        // Block 3L, LOGSCL - Compute log scale factor
603        let wd2 = LOG_SCALE_FACTOR_MAP[wd1 as usize];
604        let mut wd1 = (self.band[0].quantizer_step_size * 127) >> 7;
605        wd1 += SCALE_FACTOR_ADJUST_LOW[wd2 as usize];
606        self.band[0].quantizer_step_size = wd1.clamp(0, 18432);
607
608        // Block 3L, SCALEL - Compute quantizer scale factor
609        let wd1 = (self.band[0].quantizer_step_size >> 6) & 31;
610        let wd2 = 8 - (self.band[0].quantizer_step_size >> 11);
611        let wd3 = if wd2 < 0 {
612            INV_LOG_BASE[wd1 as usize] << -wd2
613        } else {
614            INV_LOG_BASE[wd1 as usize] >> wd2
615        };
616        self.band[0].log_scale_factor = wd3 << 2;
617
618        // Apply predictor adaptation
619        block4(&mut self.band[0], dlowt);
620
621        rlow
622    }
623
624    /// Process the high band component of the G.722 stream
625    #[inline]
626    fn process_high_band(&mut self, ihigh: i32) -> i32 {
627        // Block 2H, INVQAH - Inverse quantizer for high band
628        let wd2 = QUANT_MULT_HIGH_2BIT[ihigh as usize];
629        let dhigh = (self.band[1].log_scale_factor * wd2) >> 15;
630
631        // Block 5H, RECONS - Reconstruction of high band signal
632        let rhigh = dhigh + self.band[1].signal_estimate;
633
634        // Block 6H, LIMIT - Limiting to valid range
635        let rhigh = rhigh.clamp(-16384, 16383);
636
637        // Block 2H, INVQAH - Adaptation logic
638        let wd2 = HIGH_LOG_SCALE_MAP[ihigh as usize];
639        let mut wd1 = (self.band[1].quantizer_step_size * 127) >> 7;
640        wd1 += SCALE_FACTOR_ADJUST_HIGH[wd2 as usize];
641        self.band[1].quantizer_step_size = wd1.clamp(0, 22528);
642
643        // Block 3H, SCALEH - Compute quantizer scale factor
644        let wd1 = (self.band[1].quantizer_step_size >> 6) & 31;
645        let wd2 = 10 - (self.band[1].quantizer_step_size >> 11);
646        let wd3 = if wd2 < 0 {
647            INV_LOG_BASE[wd1 as usize] << -wd2
648        } else {
649            INV_LOG_BASE[wd1 as usize] >> wd2
650        };
651        self.band[1].log_scale_factor = wd3 << 2;
652
653        // Apply predictor adaptation
654        block4(&mut self.band[1], dhigh);
655
656        rhigh
657    }
658
659    /// Apply QMF synthesis filter to combine low and high band signals
660    #[inline]
661    fn apply_qmf_synthesis(&mut self, rlow: i32, rhigh: i32) -> [i16; 2] {
662        // Shift filter state
663        self.x.copy_within(2..24, 0);
664
665        // Set new filter state values
666        self.x[22] = rlow + rhigh;
667        self.x[23] = rlow - rhigh;
668
669        // Apply QMF synthesis filter (unrolled loop for 12 coefficients)
670        let mut xout2 = self.x[0] * QMF_FILTER_COEFS[0];
671        xout2 += self.x[2] * QMF_FILTER_COEFS[1];
672        xout2 += self.x[4] * QMF_FILTER_COEFS[2];
673        xout2 += self.x[6] * QMF_FILTER_COEFS[3];
674        xout2 += self.x[8] * QMF_FILTER_COEFS[4];
675        xout2 += self.x[10] * QMF_FILTER_COEFS[5];
676        xout2 += self.x[12] * QMF_FILTER_COEFS[6];
677        xout2 += self.x[14] * QMF_FILTER_COEFS[7];
678        xout2 += self.x[16] * QMF_FILTER_COEFS[8];
679        xout2 += self.x[18] * QMF_FILTER_COEFS[9];
680        xout2 += self.x[20] * QMF_FILTER_COEFS[10];
681        xout2 += self.x[22] * QMF_FILTER_COEFS[11];
682
683        let mut xout1 = self.x[1] * QMF_FILTER_COEFS[11];
684        xout1 += self.x[3] * QMF_FILTER_COEFS[10];
685        xout1 += self.x[5] * QMF_FILTER_COEFS[9];
686        xout1 += self.x[7] * QMF_FILTER_COEFS[8];
687        xout1 += self.x[9] * QMF_FILTER_COEFS[7];
688        xout1 += self.x[11] * QMF_FILTER_COEFS[6];
689        xout1 += self.x[13] * QMF_FILTER_COEFS[5];
690        xout1 += self.x[15] * QMF_FILTER_COEFS[4];
691        xout1 += self.x[17] * QMF_FILTER_COEFS[3];
692        xout1 += self.x[19] * QMF_FILTER_COEFS[2];
693        xout1 += self.x[21] * QMF_FILTER_COEFS[1];
694        xout1 += self.x[23] * QMF_FILTER_COEFS[0];
695
696        // Return reconstructed samples with proper scaling
697        [saturate(xout1 >> 11) as i16, saturate(xout2 >> 11) as i16]
698    }
699
700    /// Decodes a G.722 frame and returns PCM samples
701    /// This is the main decoding function that processes G.722 encoded data
702    pub fn decode_frame(&mut self, data: &[u8]) -> PcmBuf {
703        let mut output = Vec::with_capacity(data.len() * 2);
704        let mut idx = 0;
705
706        if self.eight_k {
707            while idx < data.len() {
708                let code = self.extract_code(data, &mut idx);
709                let (wd1, _, wd2) = self.parse_code(code);
710                let rlow = self.process_low_band(wd1, wd2);
711                output.push((rlow << 1) as i16);
712            }
713        } else {
714            while idx < data.len() {
715                let code = self.extract_code(data, &mut idx);
716                let (wd1, ihigh, wd2) = self.parse_code(code);
717                let rlow = self.process_low_band(wd1, wd2);
718                let rhigh = self.process_high_band(ihigh);
719                let pcm = self.apply_qmf_synthesis(rlow, rhigh);
720                output.extend_from_slice(&pcm);
721            }
722        }
723        output
724    }
725}
726
727impl Encoder for G722Encoder {
728    fn encode(&mut self, samples: &[Sample]) -> Vec<u8> {
729        self.g722_encode(samples)
730    }
731
732    fn sample_rate(&self) -> u32 {
733        16000 // G.722 encoding sample rate is 16kHz
734    }
735
736    fn channels(&self) -> u16 {
737        1 // G.722 is mono encoding
738    }
739}
740
741impl Decoder for G722Decoder {
742    fn decode(&mut self, data: &[u8]) -> PcmBuf {
743        self.decode_frame(data)
744    }
745
746    fn sample_rate(&self) -> u32 {
747        16000
748    }
749
750    fn channels(&self) -> u16 {
751        1
752    }
753}