Line data Source code
1 : /******************************************************************************
2 : * ETSI TS 103 634 V1.5.1 *
3 : * Low Complexity Communication Codec Plus (LC3plus) *
4 : * *
5 : * Copyright licence is solely granted through ETSI Intellectual Property *
6 : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
7 : * estoppel or otherwise. *
8 : ******************************************************************************/
9 :
10 : #include "functions.h"
11 :
12 : static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x);
13 :
14 : /*************************************************************************/
15 :
16 0 : void processTnsDecoder_fx(Word16 rc_idx[], Word32 x[], Word16 xLen, Word16 order[], Word16 *x_e, Word16 BW_stopband_idx,
17 : Word16 frame_dms, Word8 *scratchBuffer
18 : #ifdef ENABLE_HR_MODE
19 : , Word16 hrmode
20 : #endif
21 : )
22 : {
23 : Dyn_Mem_Deluxe_In(
24 : Word32 *state;
25 : Counter i, j;
26 : Word16 s1, s2, s, *rc, f, stopfreq, BW_stopband;
27 : Word16 numfilters, startfreq[TNS_NUMFILTERS_MAX];
28 : );
29 :
30 0 : state = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = MAXLAG */
31 0 : rc = (Word16 *)scratchAlign(state, sizeof(*state) * MAXLAG); /* Size = MAXLAG */
32 :
33 0 : numfilters = 1;
34 :
35 : #ifdef ENABLE_HR_MODE
36 0 : if (hrmode == 1)
37 : {
38 0 : BW_stopband = BW_cutoff_bin_all_HR[BW_stopband_idx]; move16();
39 : }
40 : else
41 : #endif
42 : {
43 0 : BW_stopband = BW_cutoff_bin_all[BW_stopband_idx]; move16();
44 : }
45 :
46 0 : SWITCH (frame_dms)
47 : {
48 0 : case 25:
49 0 : startfreq[0] = 3; move16();
50 0 : BW_stopband = shr_pos(BW_stopband, 2);
51 0 : BREAK;
52 0 : case 50:
53 0 : startfreq[0] = 6; move16();
54 0 : BW_stopband = shr_pos(BW_stopband, 1);
55 0 : BREAK;
56 0 : case 75:
57 0 : startfreq[0] = 9; move16();
58 0 : BW_stopband = add(shr_pos(BW_stopband, 2), add(shr_pos(BW_stopband, 2), shr_pos(BW_stopband, 2)));
59 0 : BREAK;
60 0 : case 100: startfreq[0] = 12; BREAK;
61 : }
62 :
63 0 : IF (sub(BW_stopband_idx, 3) >= 0 && frame_dms >= 50)
64 : {
65 0 : numfilters = 2;
66 0 : startfreq[1] = shr_pos(BW_stopband, 1);
67 : }
68 0 : stopfreq = 0;
69 :
70 0 : test(); test();
71 0 : IF (order[0] > 0 || (sub(numfilters, 2) == 0 && order[1] > 0))
72 : {
73 : /* Scaling */
74 0 : f = startfreq[0]; move16();
75 0 : test();
76 0 : IF (sub(numfilters, 2) == 0 && order[0] == 0)
77 : {
78 0 : f = startfreq[1]; move16();
79 : }
80 0 : s1 = getScaleFactor32_lc3plus(x, f);
81 0 : s2 = getScaleFactor32_lc3plus(x + f, sub(xLen, f));
82 0 : s = s_min(s1, sub(s2, 7)); /* 7 bits of headroom for IIR filtering */
83 0 : *x_e = sub(*x_e, s);
84 :
85 : /* Init Filter */
86 0 : basop_memset(state, 0, MAXLAG * sizeof(Word32));
87 0 : FOR (i = 0; i < f; i++)
88 : {
89 0 : x[i] = L_shl(x[i], s); move32();
90 : }
91 :
92 0 : FOR (j = 0; j < numfilters; j++)
93 : {
94 0 : IF (order[j] > 0)
95 : {
96 : /* Unquantize coefficients */
97 0 : FOR (i = 0; i < order[j]; i++)
98 : {
99 0 : rc[i] = tnsQuantPts[rc_idx[j * MAXLAG + i]]; move16();
100 : }
101 :
102 : /* Stop frequency */
103 0 : stopfreq = BW_stopband; move16();
104 0 : IF (sub(numfilters, 2) == 0 && j == 0)
105 : {
106 0 : stopfreq = startfreq[1];
107 : }
108 :
109 : /* Filter */
110 0 : FOR (i = startfreq[j]; i < stopfreq; i++)
111 : {
112 0 : x[i] = IIRLattice(order[j], rc, state, L_shl(x[i], s)); move32();
113 : }
114 : }
115 : }
116 0 : FOR (i = stopfreq; i < xLen; i++)
117 : {
118 0 : x[i] = L_shl(x[i], s); move32();
119 : }
120 : }
121 : Dyn_Mem_Deluxe_Out();
122 0 : }
123 :
124 : /*************************************************************************/
125 : /*************************************************************************/
126 : /*************************************************************************/
127 :
128 0 : static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x)
129 : {
130 : Dyn_Mem_Deluxe_In(
131 : Counter i;
132 : );
133 :
134 : /* first stage: no need to calculate state[order-1] */
135 0 : x = L_sub_sat(x, Mpy_32_16_lc3plus(state[order - 1], parCoeff[order - 1]));
136 :
137 0 : FOR (i = order - 2; i >= 0; i--)
138 : {
139 0 : x = L_sub(x, Mpy_32_16_lc3plus(state[i], parCoeff[i]));
140 0 : state[i + 1] = L_add(state[i], Mpy_32_16_lc3plus(x, parCoeff[i])); move32();
141 : }
142 :
143 0 : state[0] = x; move32();
144 :
145 : Dyn_Mem_Deluxe_Out();
146 0 : return x;
147 : }
148 :
|