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 "defines.h"
11 : #include "functions.h"
12 :
13 : /*
14 : * processTdac_fx
15 : *
16 : * Parameters:
17 : * ola_mem o: pointer of output signal Q0
18 : * ola_mem_exp o: exponent of output signal Q0
19 : * synth i: pointer of input signal Q0
20 : * synth_exp i: exponent of input signal Q0
21 : * win i: pointer of analysis and synthesis window Q0
22 : * la_zeroes i: number of zeroes Q0
23 : * frame_len i: frame length Q0
24 : *
25 : * Function:
26 : *
27 : *
28 : * Returns:
29 : * void
30 : */
31 0 : void processTdac_fx(Word16 *ola_mem, Word16 *ola_mem_exp, const Word16 *synth_inp, const Word16 synth_exp_inp,
32 : #ifdef ENABLE_HR_MODE
33 : const Word32 *win,
34 : #else
35 : const Word16 *win,
36 : #endif
37 : const Word16 la_zeroes, const Word16 frame_len, Word8 *scratchBuffer)
38 : {
39 : Counter i;
40 : Word16 s;
41 : Word16 L;
42 : Word16 N;
43 : Word16 NZ;
44 : Word16 LD2;
45 : Word32 sz;
46 : Word16 INV_NORM;
47 : Word16 INV_NORM_E;
48 : Word16 smax;
49 : Word16 * synth;
50 : Word16 synth_len;
51 : Word16 synth_exp;
52 : #ifdef ENABLE_HR_MODE
53 : const Word32 *win1, *win2, *win3, *win4;
54 : #else
55 : const Word16 *win1, *win2, *win3, *win4;
56 : #endif
57 : const Word16 *synth1;
58 : const Word16 *synth2;
59 : Word16 * ola_mem1;
60 : Word16 * ola_mem2;
61 :
62 : #ifdef DYNMEM_COUNT
63 : Dyn_Mem_In("processTdac_fx", sizeof(struct {
64 : Counter i;
65 : Word16 s;
66 : Word16 L;
67 : Word16 N;
68 : Word16 NZ;
69 : Word16 LD2;
70 : Word32 sz;
71 : Word16 INV_NORM;
72 : Word16 INV_NORM_E;
73 : Word16 smax;
74 : Word16 * synth;
75 : Word16 synth_len;
76 : Word16 synth_exp;
77 : const Word16 *win1;
78 : const Word16 *win2;
79 : const Word16 *win3;
80 : const Word16 *win4;
81 : const Word16 *synth1;
82 : const Word16 *synth2;
83 : Word16 * ola_mem1;
84 : Word16 * ola_mem2;
85 : }));
86 : #endif
87 :
88 0 : synth = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN */
89 :
90 0 : ASSERT(la_zeroes <= frame_len / 2);
91 :
92 0 : L = frame_len; move16();
93 0 : LD2 = shr_pos(L, 1);
94 0 : NZ = sub(LD2, la_zeroes);
95 :
96 : /* inverse normalization of sqrt(2/N) inside window */
97 : #ifdef ENABLE_HR_MODE
98 0 : IF ((sub(frame_len, 960) == 0) || (sub(frame_len, 720) == 0))
99 : {
100 0 : INV_NORM = negate(shl_pos(frame_len, (15 - 10)));
101 0 : INV_NORM_E = 3; move16();
102 : }
103 : ELSE
104 : #endif
105 : {
106 0 : INV_NORM = negate(shl_pos(frame_len, (15 - 9)));
107 0 : INV_NORM_E = 2; move16();
108 0 : if (norm_s(INV_NORM) > 0)
109 : {
110 0 : INV_NORM = shl_pos(INV_NORM, 1);
111 0 : INV_NORM_E = 1; move16();
112 : }
113 0 : if (sub(frame_len, 120) <= 0)
114 : {
115 0 : INV_NORM_E = add(INV_NORM_E, 2);
116 : }
117 0 : if (sub(frame_len, 20) <= 0)
118 : {
119 0 : INV_NORM_E = add(INV_NORM_E, 2);
120 : }
121 : }
122 :
123 : /* Scale input */
124 0 : synth_len = sub(shl_pos(L, 1), la_zeroes);
125 0 : s = getScaleFactor16(synth_inp, synth_len);
126 :
127 0 : FOR (i = 0; i < synth_len; i++)
128 : {
129 0 : synth[i] = shl(synth_inp[i], s); move16();
130 : }
131 0 : synth_exp = sub(synth_exp_inp, s);
132 :
133 : /* calculate x_ov[L+la_zeroes] ... x_ov[2*L-1] */
134 :
135 0 : win1 = &win[L + LD2 - 1];
136 0 : win2 = &win[L + LD2];
137 :
138 0 : win3 = &win[LD2 - 1];
139 0 : win4 = &win[LD2];
140 :
141 0 : synth1 = &synth[L + LD2 - 1 - la_zeroes];
142 0 : synth2 = &synth[L + LD2 - la_zeroes];
143 :
144 0 : ola_mem1 = &ola_mem[LD2 - la_zeroes];
145 0 : ola_mem2 = &ola_mem[LD2 - la_zeroes - 1];
146 :
147 0 : smax = 15; move16();
148 :
149 0 : FOR (i = 0; i < NZ; i++)
150 : {
151 : /* analysis windowing + 2N -> N */
152 0 : sz = L_mac_sat(L_mult(*synth1, extractW16(*win1)), *synth2, extractW16(*win2));
153 :
154 : /* N -> 2N + synthesis windowing */
155 0 : *ola_mem1 = round_fx(Mpy_32_16_lc3plus(sz, extractW16(*win3))); move16();
156 0 : *ola_mem2 = round_fx(Mpy_32_16_lc3plus(sz, extractW16(*win4))); move16();
157 :
158 : /* determine headroom */
159 0 : s = norm_s(*ola_mem1);
160 0 : if (*ola_mem1 != 0)
161 0 : smax = s_min(smax, s);
162 0 : s = norm_s(*ola_mem2);
163 0 : if (*ola_mem2 != 0)
164 0 : smax = s_min(smax, s);
165 :
166 : /* pointer update */
167 0 : win1--;
168 0 : win2++;
169 0 : win3--;
170 0 : win4++;
171 0 : synth1--;
172 0 : synth2++;
173 0 : ola_mem1++;
174 0 : ola_mem2--;
175 : }
176 :
177 0 : N = LD2; move16();
178 :
179 0 : FOR (; i < N; i++)
180 : {
181 : /* analysis windowing + 2N -> N */
182 0 : sz = L_mult(*synth1, extractW16(*win1));
183 :
184 : /* N -> 2N + synthesis windowing */
185 0 : *ola_mem1 = round_fx(Mpy_32_16_lc3plus(sz, extractW16(*win3))); move16();
186 :
187 : /* determin headroom */
188 0 : s = norm_s(*ola_mem1);
189 0 : if (*ola_mem1 != 0)
190 0 : smax = s_min(smax, s);
191 :
192 : /* pointer update */
193 0 : win1--;
194 0 : win2++;
195 0 : win3--;
196 0 : synth1--;
197 0 : synth2++;
198 0 : ola_mem1++;
199 : }
200 :
201 0 : smax = s_min(smax, 15);
202 :
203 0 : N = add(N, NZ);
204 :
205 0 : FOR (i = 0; i < N; i++)
206 : {
207 0 : ola_mem[i] = round_fx(L_mult(shl(ola_mem[i], smax), INV_NORM)); move16();
208 : }
209 :
210 0 : *ola_mem_exp = sub(add(synth_exp, INV_NORM_E), smax); move16();
211 :
212 : #ifdef DYNMEM_COUNT
213 : Dyn_Mem_Out();
214 : #endif
215 0 : }
216 :
217 :
|