voice_engine/media/codecs/
g722.rs

1use super::{Decoder, Encoder};
2use crate::{media::PcmBuf, media::Sample};
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    /// Sign bits storage [current signal, previous, ..., previous-5]
114    sign_bits: [i32; 7],
115    /// Log scale factor (used for quantization and dequantization)
116    log_scale_factor: i32,
117    /// Quantizer step size (used for adaptive quantization)
118    quantizer_step_size: i32,
119}
120
121fn saturate(amp: i32) -> i32 {
122    amp.clamp(i16::MIN as i32, i16::MAX as i32)
123}
124
125/// Process Block 4 operations for G.722 ADPCM algorithm
126/// This function performs the predictor adaptation and reconstruction steps
127/// as defined in the G.722 standard
128fn block4(band: &mut G722Band, d: i32) {
129    // Block 4, RECONS - Reconstruct the signal
130    // Set current prediction difference
131    band.difference_signal[0] = d;
132    // Reconstruct signal by adding signal estimate to difference signal
133    band.reconstructed_signal[0] = saturate(band.signal_estimate + d);
134
135    // Block 4, PARREC - Partial reconstruction
136    // Used for predictor adaptation
137    band.partial_reconstructed[0] = saturate(band.zero_filter_output + d);
138
139    // Block 4, UPPOL2 - Update second predictor coefficient
140    // Extract sign bits for adaptation logic
141    for i in 0..3 {
142        band.sign_bits[i] = band.partial_reconstructed[i] >> 15;
143    }
144
145    // Scale first predictor coefficient
146    let a1_scaled = saturate(band.pole_coefficients[1] << 2);
147
148    // Apply sign correlation logic for adaptation direction
149    let mut a2_update = if band.sign_bits[0] == band.sign_bits[1] {
150        -a1_scaled
151    } else {
152        a1_scaled
153    };
154    a2_update = a2_update.min(32767);
155
156    // Apply second level of adaptation based on older samples
157    let mut a2_adj = a2_update >> 7;
158    if band.sign_bits[0] == band.sign_bits[2] {
159        a2_adj += 128;
160    } else {
161        a2_adj -= 128;
162    }
163
164    // Complete second coefficient update with leakage factor
165    a2_adj += (band.pole_coefficients[2] * 32512) >> 15;
166
167    // Limit the coefficient range to prevent instability
168    band.pole_coefficients_temp[2] = a2_adj.clamp(-12288, 12288);
169
170    // Block 4, UPPOL1 - Update first predictor coefficient
171    band.sign_bits[0] = band.partial_reconstructed[0] >> 15; // Current sign
172    band.sign_bits[1] = band.partial_reconstructed[1] >> 15; // Previous sign
173
174    // Apply sign correlation logic for first coefficient
175    let sign_factor = if band.sign_bits[0] == band.sign_bits[1] {
176        192
177    } else {
178        -192
179    };
180    let leakage = (band.pole_coefficients[1] * 32640) >> 15;
181
182    // Calculate new coefficient with both sign and leakage factors
183    band.pole_coefficients_temp[1] = saturate(sign_factor + leakage);
184
185    // Calculate adjustment limit based on second coefficient
186    let limit = saturate(15360 - band.pole_coefficients_temp[2]);
187
188    // Constrain first coefficient based on second coefficient
189    // This prevents instability in the filter
190    if band.pole_coefficients_temp[1] > limit {
191        band.pole_coefficients_temp[1] = limit;
192    } else if band.pole_coefficients_temp[1] < -limit {
193        band.pole_coefficients_temp[1] = -limit;
194    }
195
196    // Block 4, UPZERO - Update zero section (FIR) coefficients
197    let step_size = if d == 0 { 0 } else { 128 };
198    band.sign_bits[0] = d >> 15; // Sign of current difference
199
200    // Update each zero filter coefficient
201    for i in 1..7 {
202        band.sign_bits[i] = band.difference_signal[i] >> 15; // Extract sign
203        // Apply sign correlation logic for adaptation direction
204        let adj = if band.sign_bits[i] == band.sign_bits[0] {
205            step_size
206        } else {
207            -step_size
208        };
209        // Apply leakage factor
210        let leakage = (band.zero_coefficients[i] * 32640) >> 15;
211        // Calculate new coefficient
212        band.zero_coefficients_temp[i] = saturate(adj + leakage);
213    }
214
215    // Block 4, DELAYA - Delay updates for filter memory
216    // Shift the difference signal memory
217    for i in (1..7).rev() {
218        band.difference_signal[i] = band.difference_signal[i - 1];
219    }
220
221    // Update filter coefficients
222    for i in 1..7 {
223        band.zero_coefficients[i] = band.zero_coefficients_temp[i];
224    }
225
226    // Shift pole filter memory
227    for i in (1..3).rev() {
228        band.reconstructed_signal[i] = band.reconstructed_signal[i - 1];
229        band.partial_reconstructed[i] = band.partial_reconstructed[i - 1];
230        band.pole_coefficients[i] = band.pole_coefficients_temp[i];
231    }
232
233    // Block 4, FILTEP - Pole section (IIR) filtering
234    // Calculate contribution of the pole section to the signal estimate
235    let r1_adj = saturate(band.reconstructed_signal[1] + band.reconstructed_signal[1]); // Scale by 2
236    let pole1 = (band.pole_coefficients[1] * r1_adj) >> 15;
237
238    let r2_adj = saturate(band.reconstructed_signal[2] + band.reconstructed_signal[2]); // Scale by 2
239    let pole2 = (band.pole_coefficients[2] * r2_adj) >> 15;
240
241    // Combined pole section output
242    band.pole_filter_output = saturate(pole1 + pole2);
243
244    // Block 4, FILTEZ - Zero section (FIR) filtering
245    // Calculate contribution of the zero section to the signal estimate
246    band.zero_filter_output = 0;
247    for i in 1..7 {
248        let d_adj = saturate(band.difference_signal[i] + band.difference_signal[i]); // Scale by 2
249        band.zero_filter_output += (band.zero_coefficients[i] * d_adj) >> 15;
250    }
251    band.zero_filter_output = saturate(band.zero_filter_output);
252
253    // Block 4, PREDIC - Prediction
254    // Final signal estimate is sum of pole and zero section outputs
255    band.signal_estimate = saturate(band.pole_filter_output + band.zero_filter_output);
256}
257
258pub struct G722Encoder {
259    packed: bool,
260    eight_k: bool,
261    bits_per_sample: i32,
262    x: [i32; 24],
263    band: [G722Band; 2],
264    out_buffer: u32,
265    out_bits: i32,
266}
267
268pub struct G722Decoder {
269    packed: bool,
270    eight_k: bool,
271    bits_per_sample: i32,
272    x: [i32; 24],
273    band: [G722Band; 2],
274    in_buffer: u32,
275    in_bits: i32,
276}
277
278impl G722Encoder {
279    pub fn new() -> Self {
280        Self::with_options(Bitrate::Mode1_64000, false, false)
281    }
282
283    /// Creates an encoder with specified bitrate and options
284    pub fn with_options(rate: Bitrate, eight_k: bool, packed: bool) -> Self {
285        let mut encoder = Self {
286            packed,
287            eight_k,
288            bits_per_sample: rate.bits_per_sample(),
289            x: [0; 24],
290            band: [G722Band::default(), G722Band::default()],
291            out_buffer: 0,
292            out_bits: 0,
293        };
294
295        // Initialize band states with correct starting values
296        encoder.band[0].log_scale_factor = 32 << 2; // Initial det value for lower band
297        encoder.band[1].log_scale_factor = 8 << 2; // Initial det value for upper band
298
299        encoder
300    }
301
302    /// Encode 16-bit PCM samples into G.722 format
303    /// This function follows the G.722 standard algorithm exactly
304    fn g722_encode(&mut self, amp: &[i16]) -> Vec<u8> {
305        // Pre-allocate output buffer with appropriate capacity
306        let mut output = Vec::with_capacity(amp.len() / 2 + 1);
307
308        // Initialize processing variables for low and high bands
309        let mut xlow: i32;
310        let mut xhigh: i32 = 0;
311        let mut input_idx = 0;
312
313        // Process all input samples
314        while input_idx < amp.len() {
315            // Split input into low and high bands based on mode
316            if self.eight_k {
317                // 8kHz mode - Just use input directly with scaling
318                xlow = amp[input_idx] as i32 >> 1;
319                input_idx += 1;
320            } else {
321                // 16kHz mode - Apply QMF analysis filter to split bands
322                // Shuffle buffer down to make room for new samples
323                for i in 0..22 {
324                    self.x[i] = self.x[i + 2];
325                }
326
327                // Add new samples to buffer
328                self.x[22] = amp[input_idx] as i32;
329                input_idx += 1;
330                self.x[23] = if input_idx < amp.len() {
331                    amp[input_idx] as i32
332                } else {
333                    0 // Handle edge case at end of buffer
334                };
335                input_idx += 1;
336
337                // Apply QMF filter to split input into bands
338                let mut sumeven = 0;
339                let mut sumodd = 0;
340                for i in 0..12 {
341                    sumodd += self.x[2 * i] * QMF_FILTER_COEFS[i];
342                    sumeven += self.x[2 * i + 1] * QMF_FILTER_COEFS[11 - i];
343                }
344
345                // Scale filter outputs to get low and high bands
346                xlow = (sumeven + sumodd) >> 14;
347                xhigh = (sumeven - sumodd) >> 14;
348            }
349
350            // Process low band (always performed)
351            let code = if self.eight_k {
352                // 8kHz mode - only low band matters
353                self.encode_low_band(xlow, true)
354            } else {
355                // 16kHz mode - encode both bands
356                let ilow = self.encode_low_band(xlow, false);
357                let ihigh = self.encode_high_band(xhigh);
358                (ihigh << 6 | ilow) >> (8 - self.bits_per_sample)
359            };
360
361            // Output the encoded code
362            self.output_code(code, &mut output);
363        }
364
365        // Handle any remaining bits in the output buffer
366        if self.packed && self.out_bits > 0 {
367            output.push((self.out_buffer & 0xFF) as u8);
368        }
369
370        output
371    }
372
373    /// Encode low band sample and update state
374    /// Returns the encoded low band bits
375    fn encode_low_band(&mut self, xlow: i32, is_eight_k: bool) -> i32 {
376        // Block 1L, SUBTRA - Calculate difference signal
377        let el = saturate(xlow - self.band[0].signal_estimate);
378
379        // Block 1L, QUANTL - Quantize difference signal
380        let wd = if el >= 0 { el } else { -(el + 1) };
381
382        // Find quantization interval
383        let mut quantization_idx = 1;
384        while quantization_idx < 30 {
385            let decision_level =
386                (QUANT_DECISION_LEVEL[quantization_idx] * self.band[0].log_scale_factor) >> 12;
387            if wd < decision_level {
388                break;
389            }
390            quantization_idx += 1;
391        }
392
393        // Select output bits based on sign
394        let ilow = if el < 0 {
395            QUANT_INDEX_NEG[quantization_idx]
396        } else {
397            QUANT_INDEX_POS[quantization_idx]
398        };
399
400        // Block 2L, INVQAL - Inverse quantize for prediction
401        let ril = ilow >> 2;
402        let wd2 = QUANT_MULT_LOW_4BIT[ril as usize];
403        let dlow = (self.band[0].log_scale_factor * wd2) >> 15;
404
405        // Block 3L, LOGSCL - Update scale factor
406        let il4 = LOG_SCALE_FACTOR_MAP[ril as usize];
407        let mut nb = (self.band[0].quantizer_step_size * 127) >> 7;
408        nb += SCALE_FACTOR_ADJUST_LOW[il4 as usize];
409        self.band[0].quantizer_step_size = nb.clamp(0, 18432);
410
411        // Block 3L, SCALEL - Compute new quantizer scale factor
412        let wd1 = self.band[0].quantizer_step_size >> 6 & 31;
413        let wd2 = 8 - (self.band[0].quantizer_step_size >> 11);
414        let wd3 = if wd2 < 0 {
415            INV_LOG_BASE[wd1 as usize] << -wd2
416        } else {
417            INV_LOG_BASE[wd1 as usize] >> wd2
418        };
419        self.band[0].log_scale_factor = wd3 << 2;
420
421        // Apply predictor adaptation (ADPCM core algorithm)
422        block4(&mut self.band[0], dlow);
423
424        // Return appropriate value based on mode
425        if is_eight_k {
426            ((0xc0 | ilow) >> 8) - self.bits_per_sample
427        } else {
428            ilow
429        }
430    }
431
432    /// Encode high band sample and update state
433    /// Returns the encoded high band bits
434    fn encode_high_band(&mut self, xhigh: i32) -> i32 {
435        // Block 1H, SUBTRA - Calculate difference signal
436        let eh = saturate(xhigh - self.band[1].signal_estimate);
437
438        // Block 1H, QUANTH - Quantize difference signal
439        let wd = if eh >= 0 { eh } else { -(eh + 1) };
440        let decision_level = (564 * self.band[1].log_scale_factor) >> 12;
441
442        // Determine quantization level for high band (2-bit)
443        let mih = if wd >= decision_level { 2 } else { 1 };
444        let ihigh = if eh < 0 {
445            HIGH_QUANT_INDEX_NEG[mih as usize]
446        } else {
447            HIGH_QUANT_INDEX_POS[mih as usize]
448        };
449
450        // Block 2H, INVQAH - Inverse quantize for prediction
451        let wd2 = QUANT_MULT_HIGH_2BIT[ihigh as usize];
452        let dhigh = (self.band[1].log_scale_factor * wd2) >> 15;
453
454        // Block 3H, LOGSCH - Update scale factor
455        let ih2 = HIGH_LOG_SCALE_MAP[ihigh as usize];
456        let mut nb = (self.band[1].quantizer_step_size * 127) >> 7;
457        nb += SCALE_FACTOR_ADJUST_HIGH[ih2 as usize];
458        self.band[1].quantizer_step_size = nb.clamp(0, 22528);
459
460        // Block 3H, SCALEH - Compute quantizer scale factor
461        let wd1 = self.band[1].quantizer_step_size >> 6 & 31;
462        let wd2 = 10 - (self.band[1].quantizer_step_size >> 11);
463        let wd3 = if wd2 < 0 {
464            INV_LOG_BASE[wd1 as usize] << -wd2
465        } else {
466            INV_LOG_BASE[wd1 as usize] >> wd2
467        };
468        self.band[1].log_scale_factor = wd3 << 2;
469
470        // Apply predictor adaptation (ADPCM core algorithm)
471        block4(&mut self.band[1], dhigh);
472
473        ihigh
474    }
475
476    /// Add encoded bits to the output buffer
477    fn output_code(&mut self, code: i32, output: &mut Vec<u8>) {
478        if self.packed {
479            // Pack the code bits across byte boundaries
480            self.out_buffer |= (code as u32) << self.out_bits;
481            self.out_bits += self.bits_per_sample;
482
483            // When we have at least 8 bits, output a byte
484            if self.out_bits >= 8 {
485                output.push((self.out_buffer & 0xFF) as u8);
486                self.out_bits -= 8;
487                self.out_buffer >>= 8;
488            }
489        } else {
490            // Direct byte-aligned output
491            output.push(code as u8);
492        }
493    }
494}
495
496impl G722Decoder {
497    pub fn new() -> Self {
498        Self::with_options(Bitrate::Mode1_64000, false, false)
499    }
500
501    pub fn with_options(rate: Bitrate, packed: bool, eight_k: bool) -> Self {
502        Self {
503            packed,
504            eight_k,
505            bits_per_sample: rate.bits_per_sample(),
506            x: Default::default(),
507            band: Default::default(),
508            in_buffer: 0,
509            in_bits: 0,
510        }
511    }
512
513    /// Extracts the next G.722 code from the input data stream
514    fn extract_code(&mut self, data: &[u8], idx: &mut usize) -> i32 {
515        if self.packed {
516            // When packed, bits are combined across bytes
517            if self.in_bits < self.bits_per_sample {
518                self.in_buffer |= (data[*idx] as u32) << self.in_bits;
519                *idx += 1;
520                self.in_bits += 8;
521            }
522            let code = (self.in_buffer & ((1 << self.bits_per_sample) - 1) as u32) as i32;
523            self.in_buffer >>= self.bits_per_sample;
524            self.in_bits -= self.bits_per_sample;
525            code
526        } else {
527            // Direct byte-based access when not packed
528            let code = data[*idx] as i32;
529            *idx += 1;
530            code
531        }
532    }
533
534    /// Parses the G.722 code into low-band word and high-band index based on bit rate
535    fn parse_code(&self, code: i32) -> (i32, i32, i32) {
536        // Returns (wd1, ihigh, wd2) tuple: low-band word, high-band index, and scaled value
537        match self.bits_per_sample {
538            7 => {
539                // 56 kbit/s mode
540                let wd1 = code & 0x1f;
541                let ihigh = (code >> 5) & 0x3;
542                let wd2 = QUANT_MULT_56K[wd1 as usize];
543                (wd1 >> 1, ihigh, wd2)
544            }
545            6 => {
546                // 48 kbit/s mode
547                let wd1 = code & 0xf;
548                let ihigh = (code >> 4) & 0x3;
549                let wd2 = QUANT_MULT_LOW_4BIT[wd1 as usize];
550                (wd1, ihigh, wd2)
551            }
552            _ => {
553                // 64 kbit/s mode (default)
554                let wd1 = code & 0x3f;
555                let ihigh = (code >> 6) & 0x3;
556                let wd2 = QUANT_MULT_64K[wd1 as usize];
557                (wd1 >> 2, ihigh, wd2)
558            }
559        }
560    }
561
562    /// Process the low band component of the G.722 stream
563    fn process_low_band(&mut self, wd1: i32, wd2: i32) -> i32 {
564        // Block 5L, LOW BAND INVQBL - Inverse quantization for low band
565        let dequant = (self.band[0].log_scale_factor * wd2) >> 15;
566
567        // Block 5L, RECONS - Reconstruction of low band signal
568        let rlow = self.band[0].signal_estimate + dequant;
569
570        // Block 6L, LIMIT - Limiting to valid range
571        let rlow = rlow.clamp(-16384, 16383);
572
573        // Block 2L, INVQAL - Inverse adaptive quantizer for prediction
574        let wd2 = QUANT_MULT_LOW_4BIT[wd1 as usize];
575        let dlowt = (self.band[0].log_scale_factor * wd2) >> 15;
576
577        // Block 3L, LOGSCL - Compute log scale factor
578        let wd2 = LOG_SCALE_FACTOR_MAP[wd1 as usize];
579        let mut wd1 = (self.band[0].quantizer_step_size * 127) >> 7;
580        wd1 += SCALE_FACTOR_ADJUST_LOW[wd2 as usize];
581        self.band[0].quantizer_step_size = wd1.clamp(0, 18432);
582
583        // Block 3L, SCALEL - Compute quantizer scale factor
584        let wd1 = (self.band[0].quantizer_step_size >> 6) & 31;
585        let wd2 = 8 - (self.band[0].quantizer_step_size >> 11);
586        let wd3 = if wd2 < 0 {
587            INV_LOG_BASE[wd1 as usize] << -wd2
588        } else {
589            INV_LOG_BASE[wd1 as usize] >> wd2
590        };
591        self.band[0].log_scale_factor = wd3 << 2;
592
593        // Apply predictor adaptation
594        block4(&mut self.band[0], dlowt);
595
596        rlow
597    }
598
599    /// Process the high band component of the G.722 stream
600    fn process_high_band(&mut self, ihigh: i32) -> i32 {
601        // Block 2H, INVQAH - Inverse quantizer for high band
602        let wd2 = QUANT_MULT_HIGH_2BIT[ihigh as usize];
603        let dhigh = (self.band[1].log_scale_factor * wd2) >> 15;
604
605        // Block 5H, RECONS - Reconstruction of high band signal
606        let rhigh = dhigh + self.band[1].signal_estimate;
607
608        // Block 6H, LIMIT - Limiting to valid range
609        let rhigh = rhigh.clamp(-16384, 16383);
610
611        // Block 2H, INVQAH - Adaptation logic
612        let wd2 = HIGH_LOG_SCALE_MAP[ihigh as usize];
613        let mut wd1 = (self.band[1].quantizer_step_size * 127) >> 7;
614        wd1 += SCALE_FACTOR_ADJUST_HIGH[wd2 as usize];
615        self.band[1].quantizer_step_size = wd1.clamp(0, 22528);
616
617        // Block 3H, SCALEH - Compute quantizer scale factor
618        let wd1 = (self.band[1].quantizer_step_size >> 6) & 31;
619        let wd2 = 10 - (self.band[1].quantizer_step_size >> 11);
620        let wd3 = if wd2 < 0 {
621            INV_LOG_BASE[wd1 as usize] << -wd2
622        } else {
623            INV_LOG_BASE[wd1 as usize] >> wd2
624        };
625        self.band[1].log_scale_factor = wd3 << 2;
626
627        // Apply predictor adaptation
628        block4(&mut self.band[1], dhigh);
629
630        rhigh
631    }
632
633    /// Apply QMF synthesis filter to combine low and high band signals
634    fn apply_qmf_synthesis(&mut self, rlow: i32, rhigh: i32) -> [i16; 2] {
635        // Shift filter state
636        for i in 0..22 {
637            self.x[i] = self.x[i + 2];
638        }
639
640        // Set new filter state values
641        self.x[22] = rlow + rhigh;
642        self.x[23] = rlow - rhigh;
643
644        // Apply QMF synthesis filter
645        let mut xout1 = 0;
646        let mut xout2 = 0;
647
648        for i in 0..12 {
649            xout2 += self.x[2 * i] * QMF_FILTER_COEFS[i];
650            xout1 += self.x[2 * i + 1] * QMF_FILTER_COEFS[11 - i];
651        }
652
653        // Return reconstructed samples with proper scaling
654        [saturate(xout1 >> 11) as i16, saturate(xout2 >> 11) as i16]
655    }
656
657    /// Decodes a G.722 frame and returns PCM samples
658    /// This is the main decoding function that processes G.722 encoded data
659    pub fn decode_frame(&mut self, data: &[u8]) -> PcmBuf {
660        let mut output = Vec::with_capacity(data.len() * 2);
661        let mut idx = 0;
662
663        while idx < data.len() {
664            // Extract the next code from input data
665            let code = self.extract_code(data, &mut idx);
666
667            // Parse the code into components based on bit rate mode
668            let (wd1, ihigh, wd2) = self.parse_code(code);
669
670            // Process the low band component
671            let rlow = self.process_low_band(wd1, wd2);
672
673            if self.eight_k {
674                // 8kHz mode - use only low band with scaling
675                output.push((rlow << 1) as i16);
676            } else {
677                // 16kHz mode - process high band and combine with QMF synthesis
678                let rhigh = self.process_high_band(ihigh);
679
680                // Apply QMF synthesis filter to get reconstructed samples
681                let samples = self.apply_qmf_synthesis(rlow, rhigh);
682                output.extend_from_slice(&samples);
683            }
684        }
685
686        output
687    }
688}
689
690impl Encoder for G722Encoder {
691    fn encode(&mut self, samples: &[Sample]) -> Vec<u8> {
692        self.g722_encode(samples)
693    }
694
695    fn sample_rate(&self) -> u32 {
696        16000 // G.722 encoding sample rate is 16kHz
697    }
698
699    fn channels(&self) -> u16 {
700        1 // G.722 is mono encoding
701    }
702}
703
704impl Decoder for G722Decoder {
705    fn decode(&mut self, data: &[u8]) -> PcmBuf {
706        self.decode_frame(data)
707    }
708
709    fn sample_rate(&self) -> u32 {
710        16000
711    }
712
713    fn channels(&self) -> u16 {
714        1
715    }
716}