Skip to main content

g729_sys/g729/
post_processing.rs

1use crate::g729::basic_operations::*;
2use crate::g729::ld8k::*;
3
4/*****************************************************************************/
5/*                                                                           */
6/* Define filter coefficients                                                */
7/* Coefficient are given by the filter transfert function :                  */
8/*                                                                           */
9/*          0.46363718 - 0.92724705z(-1) + 0.46363718z(-2)                   */
10/* H(z) = −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−                  */
11/*           1 - 1.9059465z(-1) + 0.9114024z(-2)                             */
12/*                                                                           */
13/* giving:                                                                   */
14/*    y[i] = B0*x[i] + B1*x[i-1] + B2*x[i-2]                                 */
15/*                   + A1*y[i-1] + A2*y[i-2]                                 */
16/*                                                                           */
17/*****************************************************************************/
18
19/* coefficients are stored in Q1.13 */
20const A1: Word16 = 15836;
21const A2: Word16 = -7667;
22const B0: Word16 = 7699;
23const B1: Word16 = -15398;
24const B2: Word16 = 7699;
25
26/* Initialization of context values */
27pub fn init_post_processing(
28    output_y2: &mut Word32,
29    output_y1: &mut Word32,
30    input_x0: &mut Word16,
31    input_x1: &mut Word16,
32) {
33    *output_y2 = 0;
34    *output_y1 = 0;
35    *input_x0 = 0;
36    *input_x1 = 0;
37}
38
39/*****************************************************************************/
40/* postProcessing : high pass filtering and upscaling Spec 4.2.5             */
41/*      Algorithm:                                                           */
42/*      y[i] = BO*x[i] + B1*x[i-1] + B2*x[i-2] + A1*y[i-1] + A2*y[i-2]       */
43/*    parameters:                                                            */
44/*      -(i/o) decoderChannelContext : the channel context data              */
45/*      -(i/o) signal : 40 values in Q0, reconstructed speech, output        */
46/*             replaces the input in buffer                                  */
47/*                                                                           */
48/*****************************************************************************/
49pub fn post_processing(
50    output_y2: &mut Word32,
51    output_y1: &mut Word32,
52    input_x0: &mut Word16,
53    input_x1: &mut Word16,
54    signal: &mut [Word16],
55) {
56    let mut input_x2: Word16;
57    let mut acc: Word32; /* in Q13 */
58
59    for i in 0..L_SUBFRAME {
60        input_x2 = *input_x1;
61        *input_x1 = *input_x0;
62        *input_x0 = signal[i];
63
64        /* compute with acc and coefficients in Q13 */
65        acc = mult16_32_q13(A1, *output_y1); /* Y1 in Q14.13 * A1 in Q1.13 -> acc in Q17.13*/
66        acc = mac16_32_q13(acc, A2, *output_y2); /* Y2 in Q14.13 * A2 in Q0.13 -> Q15.13 + acc in Q17.13 -> acc in Q18.12 */
67        /* 3*(Xi in Q15.0 * Bi in Q0.13)->Q17.13 + acc in Q18.13 -> acc in 19.13(Overflow??) */
68        acc = mac16_16(acc, *input_x0, B0);
69        acc = mac16_16(acc, *input_x1, B1);
70        acc = saturate(mac16_16(acc, input_x2, B2), MAX_INT29); /* saturate the acc to keep in Q15.13 */
71
72        signal[i] = saturate(pshr(acc, 12), MAX_INT16 as Word32) as Word16; /* acc in Q13 -> *2 and scale back to Q0 */
73        *output_y2 = *output_y1;
74        *output_y1 = acc;
75    }
76}