audio_codec/
g722.rs

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