Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 : /*!
5 : \file
6 : \brief Complex cldfb analysis/synthesis, $Revision: 1214 $
7 : This module contains the cldfb filterbank for analysis [ cplxAnalysisCldfbFiltering() ] and
8 : synthesis [ cplxSynthesisCldfbFiltering() ]. It is a polyphase implementation of a complex
9 : exponential modulated filter bank. The analysis part usually runs at half the sample rate
10 : than the synthesis part. (So called "dual-rate" mode.)
11 :
12 : \anchor PolyphaseFiltering <h2>About polyphase filtering</h2>
13 : The polyphase implementation of a filterbank requires filtering at the input and output.
14 : This is implemented as part of cplxAnalysisCldfbFiltering() and cplxSynthesisCldfbFiltering().
15 :
16 : */
17 :
18 : #include "stl.h"
19 : #include "cnst.h"
20 : #include "stat_com.h"
21 : #include "rom_com.h"
22 : #include "basop_util.h"
23 : #include "prot_fx.h"
24 : #include <assert.h>
25 :
26 : #define STATE_BUFFER_SIZE ( 9 + 16 )
27 :
28 : #define CLDFB_NO_POLY ( 5 )
29 : #define SYN_FILTER_HEADROOM ( 1 )
30 :
31 : #define CLDFB_LDCLDFB_PFT_SCALE ( 0 )
32 : #define CLDFB_CLDFB80_O24_PFT_SCALE ( 1 )
33 : #define CLDFB_CLDFB80_O5_PFT_SCALE ( 1 )
34 : #define CLDFB_CLDFB80_PFT_SCALE ( 1 )
35 :
36 :
37 : #define SYN_FILTER_HEADROOM_1MS ( 2 )
38 : #define SYN_FILTER_HEADROOM_2MS ( 2 )
39 : #define SYN_FILTER_HEADROOM_2_5MS ( 2 )
40 : #define SYN_FILTER_HEADROOM_8MS ( 1 )
41 :
42 : #define N8 ( 4 )
43 : #define N10 ( 5 )
44 : #define N16 ( 8 )
45 : #define N20 ( 10 )
46 : #define N30 ( 15 )
47 : #define N32 ( 16 )
48 : #define N40 ( 20 )
49 : #define N60 ( 30 )
50 :
51 : static void
52 : cldfb_init_proto_and_twiddles( HANDLE_CLDFB_FILTER_BANK hs );
53 :
54 : #define cplxMpyS( yr, yi, xr, xi, cr, ci, syr, syi, sxr, sxi, CL_x, CL_z, C_c ) \
55 : CL_x = CL_form( *xr, *xi ); \
56 : C_c = C_form( *cr, *ci ); \
57 : CL_z = CL_mult_32x16( CL_x, C_c ); \
58 : *yr = CL_Extract_real( CL_z ); \
59 : *yi = CL_Extract_imag( CL_z ); \
60 : yr += syr, yi += syi, xr += sxr, xi += sxi, cr++, ci++
61 :
62 : #define cplxMpy( ryr, ryi, iyr, iyi, rxr, rxi, ixr, ixi, cr, ci, g, sx, sr, CL_x, CL_ry, CL_iy, C_c ) \
63 : CL_x = CL_form( *rxr, *rxi ); \
64 : C_c = C_form( *cr, *ci ); \
65 : CL_ry = CL_mult_32x16( CL_x, C_c ); \
66 : CL_x = CL_form( *ixr, *ixi ); \
67 : CL_iy = CL_mult_32x16( CL_x, C_c ); \
68 : CL_ry = CL_scale_t( CL_ry, g ); \
69 : CL_iy = CL_scale_t( CL_iy, g ); \
70 : ryr = CL_Extract_real( CL_ry ); \
71 : ryi = CL_Extract_imag( CL_ry ); \
72 : iyr = CL_Extract_real( CL_iy ); \
73 : iyi = CL_Extract_imag( CL_iy ); \
74 : rxr += sx, rxi += sx, ixr += sx, ixi += sx, cr += sr, ci += sr
75 :
76 : #define add1( y1, y2, y3, y4, rr12, ri12, ir12, ii12, s ) \
77 : *y1 = round_fx_sat( L_shl_sat( L_negate( L_add_sat( rr12, ii12 ) ), s ) ); \
78 : *y2 = round_fx_sat( L_shl_sat( L_negate( L_add_sat( ri12, ir12 ) ), s ) ); \
79 : *y3 = round_fx_sat( L_shl_sat( L_sub_sat( rr12, ii12 ), s ) ); \
80 : *y4 = round_fx_sat( L_shl_sat( L_sub_sat( ir12, ri12 ), s ) ); \
81 : y1 += 2, y2 -= 2, y3 -= 2, y4 += 2
82 :
83 : #define add2( y1, y2, y3, y4, rr12, ri12, ir12, ii12, s ) \
84 : *y1 = round_fx_sat( L_shl_sat( L_add_sat( ri12, ir12 ), s ) ); \
85 : *y2 = round_fx_sat( L_shl_sat( L_add_sat( rr12, ii12 ), s ) ); \
86 : *y3 = round_fx_sat( L_shl_sat( L_sub_sat( ir12, ri12 ), s ) ); \
87 : *y4 = round_fx_sat( L_shl_sat( L_sub_sat( rr12, ii12 ), s ) ); \
88 : y1 += 2, y2 -= 2, y3 -= 2, y4 += 2
89 :
90 :
91 : #define ptrUpdate16( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 ) \
92 : y11 += 2 * N8, y12 -= 2 * N8, y13 -= 2 * N8, y14 += 2 * N8, r11 -= 1 * N8; \
93 : x11 -= 2 * N8, x12 -= 2 * N8, x13 -= 2 * N8, x14 -= 2 * N8, r12 -= 1 * N8; \
94 : y21 += 2 * N8, y22 -= 2 * N8, y23 -= 2 * N8, y24 += 2 * N8, r21 += 1 * N8; \
95 : x21 += 2 * N8, x22 += 2 * N8, x23 += 2 * N8, x24 += 2 * N8, r22 += 1 * N8
96 :
97 : #define ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 ) \
98 : y11 += 2 * N10, y12 -= 2 * N10, y13 -= 2 * N10, y14 += 2 * N10, r11 -= 1 * N10; \
99 : x11 -= 2 * N10, x12 -= 2 * N10, x13 -= 2 * N10, x14 -= 2 * N10, r12 -= 1 * N10; \
100 : y21 += 2 * N10, y22 -= 2 * N10, y23 -= 2 * N10, y24 += 2 * N10, r21 += 1 * N10; \
101 : x21 += 2 * N10, x22 += 2 * N10, x23 += 2 * N10, x24 += 2 * N10, r22 += 1 * N10
102 :
103 :
104 0 : static void cplxMultAdd10_1( Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, Word16 sx, Word16 sr )
105 : {
106 : Word32 rr12, ri12, ir12, ii12;
107 : cmplx CL_x, CL_ry, CL_iy;
108 : cmplx_s C_c;
109 :
110 0 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
111 0 : add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
112 0 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
113 0 : add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
114 0 : }
115 :
116 0 : static void cplxMultAdd10_2( Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, Word16 sx, Word16 sr )
117 : {
118 : Word32 rr12, ri12, ir12, ii12;
119 : cmplx CL_x, CL_ry, CL_iy;
120 : cmplx_s C_c;
121 :
122 0 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
123 0 : add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
124 0 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
125 0 : add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
126 0 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
127 0 : add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
128 0 : }
129 :
130 :
131 134034 : static void cplxMultAdd20_1( Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, Word16 sx, Word16 sr )
132 : {
133 : Word32 rr12, ri12, ir12, ii12;
134 : cmplx CL_x, CL_ry, CL_iy;
135 : cmplx_s C_c;
136 :
137 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
138 134034 : add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
139 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
140 134034 : add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
141 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
142 134034 : add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
143 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
144 134034 : add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
145 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
146 134034 : add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
147 134034 : }
148 :
149 134034 : static void cplxMultAdd20_2( Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, Word16 sx, Word16 sr )
150 : {
151 : Word32 rr12, ri12, ir12, ii12;
152 : cmplx CL_x, CL_ry, CL_iy;
153 : cmplx_s C_c;
154 :
155 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
156 134034 : add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
157 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
158 134034 : add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
159 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
160 134034 : add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
161 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
162 134034 : add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
163 134034 : cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
164 134034 : add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
165 134034 : }
166 :
167 : /* calcModulation
168 :
169 : Parameters:
170 : *rYR O: pointer to real output samples (DST)
171 : *rYI O: pointer to imaginary output samples (DST)
172 : *rXR I: pointer to real input samples (DST)
173 : *rXI I: pointer to imaginary input samples (DST)
174 : srYR I: offset for update of pointer to real output samples (DST)
175 : srYI I: offset for update of pointer to imaginary output samples (DST)
176 : srXR I: offset for update of pointer to real input samples (DST)
177 : srXI I: offset for update of pointer to imaginary input samples (DST)
178 : *iYR O: pointer to real output samples (DCT)
179 : *iYI O: pointer to imaginary output samples (DCT)
180 : *iXR I: pointer to real input samples (DCT)
181 : *iXI I: pointer to imaginary input samples (DCT)
182 : siYR I: offset for update of pointer to real output samples (DCT)
183 : siYI I: offset for update of pointer to imaginary output samples (DCT)
184 : siXR I: offset for update of pointer to real input samples (DCT)
185 : siXI I: offset for update of pointer to imaginary input samples (DCT)
186 : m I: processed cldfb bands
187 :
188 : Function:
189 : The function applies for each cldfb length a unrolled complex modulation
190 :
191 : Returns:
192 : void
193 : */
194 334276 : static void calcModulation( Word32 *rYR,
195 : Word32 *rYI,
196 : Word32 *rXR,
197 : Word32 *rXI,
198 : Word16 srYR,
199 : Word16 srYI,
200 : Word16 srXR,
201 : Word16 srXI,
202 : Word32 *iYR,
203 : Word32 *iYI,
204 : Word32 *iXR,
205 : Word32 *iXI,
206 : Word16 siYR,
207 : Word16 siYI,
208 : Word16 siXR,
209 : Word16 siXI,
210 : const Word16 *rRotVctr,
211 : const Word16 *iRotVctr,
212 : Word16 m )
213 : {
214 : cmplx CL_x, CL_z;
215 : cmplx_s C_c;
216 : Word32 i;
217 334276 : Word32 lc = L_shr( m, 1 );
218 :
219 334276 : const Word16 *cr = rRotVctr;
220 334276 : const Word16 *ci = iRotVctr;
221 :
222 5890112 : FOR( i = 0; i < lc; i++ )
223 : {
224 5555836 : CL_x = CL_form( *rXR, *rXI );
225 5555836 : C_c = C_form( *cr, *ci );
226 5555836 : CL_z = CL_mult_32x16( CL_x, C_c );
227 5555836 : *rYR = CL_Extract_real( CL_z );
228 5555836 : move32();
229 5555836 : *rYI = CL_Extract_imag( CL_z );
230 5555836 : move32();
231 5555836 : rYR += srYR;
232 5555836 : rYI += srYI;
233 5555836 : rXR += srXR;
234 5555836 : rXI += srXI;
235 :
236 5555836 : CL_x = CL_form( *iXR, *iXI );
237 5555836 : CL_z = CL_mult_32x16( CL_x, C_c );
238 5555836 : *iYR = CL_Extract_real( CL_z );
239 5555836 : move32();
240 5555836 : *iYI = CL_Extract_imag( CL_z );
241 5555836 : move32();
242 5555836 : iYR += siYR;
243 5555836 : iYI += siYI;
244 5555836 : iXR += siXR;
245 5555836 : iXI += siXI;
246 5555836 : cr++;
247 5555836 : ci++;
248 : }
249 334276 : }
250 :
251 :
252 : /* calcModulationAndFolding
253 :
254 : Parameters:
255 : *rY O: pointer to folded samples (DST + DCT)
256 : *rX I: pointer to real input samples (DST)
257 : *iX I: pointer to imaginary input samples (DCT)
258 : *rRotVctr I: pointer to real modulation coefficients
259 : *iRotVctr I: pointer to imaginary modulation coefficients
260 : gain I: gain value
261 : scale I: scale factor
262 : m I: processed cldfb bands
263 : m2 I: half of processed cldfb bands
264 :
265 : Function:
266 : The function applies for each cldfb length a unrolled complex modulation with subsequent data folding
267 :
268 : Returns:
269 : void
270 : */
271 64592 : static void calcModulationAndFolding( Word16 *rY,
272 : Word32 *rX,
273 : Word32 *iX,
274 : const Word16 *rRotVctr,
275 : const Word16 *iRotVctr,
276 : Word16 gain,
277 : Word16 scale,
278 : Word16 m,
279 : Word16 m2 )
280 : {
281 : Word16 *y11, *y12, *y13, *y14;
282 : Word16 *y21, *y22, *y23, *y24;
283 : Word32 *x11, *x12, *x13, *x14;
284 : Word32 *x21, *x22, *x23, *x24;
285 : const Word16 *r11, *r12, *r21, *r22;
286 :
287 :
288 64592 : y11 = &rY[( m + m2 ) + 1];
289 64592 : y12 = &rY[m2 - 2];
290 64592 : y13 = &rY[( m + m2 ) - 2];
291 64592 : y14 = &rY[m2 + 1];
292 :
293 64592 : y21 = &rY[m + m2];
294 64592 : y22 = &rY[m2 - 1];
295 64592 : y23 = &rY[( m + m2 ) - 1];
296 64592 : y24 = &rY[m2];
297 :
298 64592 : x11 = &rX[m - 2];
299 64592 : x12 = &rX[m - 1];
300 64592 : x13 = &iX[m - 2];
301 64592 : x14 = &iX[m - 1];
302 64592 : x21 = &rX[0];
303 64592 : x22 = &rX[1];
304 64592 : x23 = &iX[0];
305 64592 : x24 = &iX[1];
306 :
307 64592 : r11 = &rRotVctr[m2 - 1];
308 64592 : r12 = &iRotVctr[m2 - 1];
309 64592 : r21 = &rRotVctr[0];
310 64592 : r22 = &iRotVctr[0];
311 :
312 64592 : SWITCH( m )
313 : {
314 0 : case 10:
315 0 : cplxMultAdd10_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
316 0 : cplxMultAdd10_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
317 0 : BREAK;
318 21712 : case 20:
319 21712 : cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
320 21712 : cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
321 21712 : BREAK;
322 26562 : case 60:
323 26562 : cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
324 26562 : cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
325 26562 : ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 );
326 : /* no break */
327 42880 : case 40:
328 42880 : cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
329 42880 : cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
330 42880 : ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 );
331 42880 : cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
332 42880 : cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
333 42880 : ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 );
334 42880 : BREAK;
335 0 : default:
336 0 : assert( 0 );
337 : }
338 64592 : }
339 :
340 :
341 : /* cldfbAnalysis_fx
342 :
343 : Parameters:
344 : cldfbBank I/O: handle to analysis CLDFB filter struct
345 : **rAnalysis O: matrix holding the real part of the subband samples
346 : **iAnalysis O: matrix holding the imaginary part of the subband samples
347 : *scaleFactor O: pointer to cldfb scalefactor struct
348 : *timeIn I: pointer to time domain data
349 : stride I: stride for time domain data
350 : *pWorkBuffer I: pointer to scratch buffer, needed for buffer of size 2*cldfbbands*Word32
351 :
352 : Function:
353 : Performs complex-valued subband filtering of the time domain data of timeIn and stores the real
354 : part of the subband samples in rAnalysis, and the imaginary part in iAnalysis
355 :
356 : Returns:
357 : void
358 : */
359 8490 : void cldfbAnalysis_fx(
360 : HANDLE_CLDFB_FILTER_BANK cldfbBank,
361 : Word32 **rAnalysis,
362 : Word32 **iAnalysis,
363 : CLDFB_SCALE_FACTOR *scaleFactor,
364 : const Word16 *timeIn, // Q(15-timeIn_e)
365 : const Word16 timeIn_e,
366 : const Word16 nTimeSlots,
367 : Word32 *pWorkBuffer // Qx
368 : )
369 :
370 : {
371 : Word16 i, k;
372 : Word16 L2, L3, L4, m, m2, M4;
373 : Word16 M0M2, M2M1, L3M1, L4M1;
374 : Word16 scale;
375 : Word16 offset;
376 : Word16 p_stride;
377 : Word16 nSamples;
378 : Word16 nSamplesUpd;
379 : Word16 stride;
380 :
381 : Word32 r1, r2;
382 : Word32 i1, i2;
383 : Word32 *rBuffer;
384 : Word32 *iBuffer;
385 : Word16 *pStates;
386 :
387 : Word16 *pStates1;
388 : Word16 *pStates2;
389 : Word16 *pStates3;
390 : Word16 *pStates4;
391 : Word16 *pStates6;
392 : Word16 *pStates5;
393 :
394 : const Word16 *rRotVctr;
395 : const Word16 *iRotVctr;
396 : const Word16 *pFilter;
397 :
398 : const Word16 *pFilter1;
399 : const Word16 *pFilter2;
400 : const Word16 *pFilter3;
401 : const Word16 *pFilter4;
402 : const Word16 *pFilter6;
403 : const Word16 *pFilter5;
404 : Word32 workBuffer[2 * BASOP_CFFT_MAX_LENGTH];
405 :
406 :
407 8490 : stride = 1; /* constant */
408 8490 : move16();
409 8490 : m = cldfbBank->no_channels;
410 8490 : move16();
411 8490 : L2 = shl( m, 1 );
412 8490 : m2 = shr( m, 1 );
413 8490 : M4 = shr( m, 2 );
414 8490 : M4 = sub( m2, M4 );
415 :
416 8490 : L3 = sub( L2, m2 );
417 8490 : L4 = add( L2, m2 );
418 :
419 8490 : M0M2 = sub( 0, m2 );
420 8490 : M2M1 = sub( m2, 1 );
421 8490 : L3M1 = sub( L3, 1 );
422 8490 : L4M1 = sub( L4, 1 );
423 :
424 8490 : rBuffer = &pWorkBuffer[0];
425 8490 : iBuffer = &pWorkBuffer[m];
426 :
427 8490 : rRotVctr = cldfbBank->rRotVctr;
428 8490 : iRotVctr = cldfbBank->iRotVctr;
429 :
430 8490 : pStates = cldfbBank->FilterStates;
431 8490 : pStates1 = &pStates[L3M1];
432 8490 : pStates2 = &pStates[L3];
433 8490 : pStates3 = &pStates[m2];
434 8490 : pStates4 = &pStates[M2M1];
435 8490 : pStates5 = &pStates[L4M1];
436 8490 : pStates6 = &pStates[M0M2];
437 :
438 8490 : p_stride = CLDFB_NO_POLY;
439 8490 : move16();
440 8490 : pFilter = &cldfbBank->p_filter[p_stride - CLDFB_NO_POLY];
441 8490 : pFilter1 = &pFilter[p_stride * L3M1];
442 8490 : pFilter2 = &pFilter[p_stride * L3];
443 8490 : pFilter3 = &pFilter[p_stride * m2];
444 8490 : pFilter4 = &pFilter[p_stride * M2M1];
445 8490 : pFilter5 = &pFilter[p_stride * L4M1];
446 8490 : pFilter6 = &pFilter[p_stride * M0M2];
447 :
448 8490 : nSamples = i_mult( nTimeSlots, cldfbBank->no_channels );
449 8490 : nSamplesUpd = i_mult( cldfbBank->no_col, cldfbBank->no_channels );
450 8490 : offset = sub( sub( cldfbBank->p_filter_length, cldfbBank->no_channels ), cldfbBank->zeros );
451 :
452 : /* Determine states scale */
453 8490 : scale = -15;
454 8490 : move16();
455 8490 : k = 0;
456 8490 : move16();
457 84900 : FOR( i = 0; i < offset; i += cldfbBank->no_channels )
458 : {
459 76410 : cldfbBank->FilterStates_e[k] = cldfbBank->FilterStates_e[( k + cldfbBank->no_col )];
460 76410 : move16();
461 76410 : assert( (size_t) k < sizeof( cldfbBank->FilterStates_e ) / sizeof( cldfbBank->FilterStates_e[0] ) );
462 76410 : scale = s_max( scale, cldfbBank->FilterStates_e[k] );
463 76410 : k = add( k, 1 );
464 : }
465 143332 : FOR( i = 0; i < nSamples; i += cldfbBank->no_channels )
466 : {
467 134842 : cldfbBank->FilterStates_e[k] = timeIn_e;
468 134842 : move16();
469 134842 : assert( (size_t) k < sizeof( cldfbBank->FilterStates_e ) / sizeof( cldfbBank->FilterStates_e[0] ) );
470 134842 : scale = s_max( scale, cldfbBank->FilterStates_e[k] );
471 134842 : k = add( k, 1 );
472 : }
473 8490 : i = s_max( scale, timeIn_e );
474 8490 : scale = sub( cldfbBank->FilterStates_eg, i );
475 8490 : cldfbBank->FilterStates_eg = i;
476 8490 : move16();
477 :
478 : /* if nTimeSlots==0, make sure we have a value. */
479 8490 : scaleFactor->lb_scale = add( cldfbBank->anaScalefactor, add( cldfbBank->FilterStates_eg, 5 ) );
480 8490 : move16();
481 :
482 : /* move and scale filter states */
483 2390034 : FOR( i = 0; i < offset; i++ )
484 : {
485 2381544 : pStates[i] = shl_sat( pStates[i + nSamplesUpd], scale ); // Q(15-(timeIn_e-FilterStates_eg))
486 2381544 : move16();
487 : }
488 :
489 : /* copy and scale current time signal */
490 8490 : scale = sub( timeIn_e, cldfbBank->FilterStates_eg );
491 4223986 : FOR( i = 0; i < nSamples; i++ )
492 : {
493 4215496 : pStates[offset + i] = shl_sat( *timeIn, scale ); // Q(15-scale)
494 4215496 : move16();
495 4215496 : timeIn = timeIn + stride;
496 : }
497 :
498 143332 : FOR( k = 0; k < nTimeSlots; k++ )
499 : {
500 1188716 : FOR( i = 0; i < M4; i++ )
501 : {
502 : /* prototype filter */
503 1053874 : r1 = L_msu0( 0, pFilter1[0 - ( p_stride * ( i * 2 ) )], pStates1[( 0 * L2 ) - ( i * 2 )] );
504 1053874 : r1 = L_msu0( r1, pFilter1[1 - ( p_stride * ( i * 2 ) )], pStates1[( 1 * L2 ) - ( i * 2 )] );
505 1053874 : r1 = L_msu0( r1, pFilter1[2 - ( p_stride * ( i * 2 ) )], pStates1[( 2 * L2 ) - ( i * 2 )] );
506 1053874 : r1 = L_msu0( r1, pFilter1[3 - ( p_stride * ( i * 2 ) )], pStates1[( 3 * L2 ) - ( i * 2 )] );
507 1053874 : r1 = L_msu0( r1, pFilter1[4 - ( p_stride * ( i * 2 ) )], pStates1[( 4 * L2 ) - ( i * 2 )] );
508 :
509 1053874 : r2 = L_msu0( 0, pFilter2[0 + ( p_stride * ( i * 2 ) )], pStates2[( 0 * L2 ) + ( i * 2 )] );
510 1053874 : r2 = L_msu0( r2, pFilter2[1 + ( p_stride * ( i * 2 ) )], pStates2[( 1 * L2 ) + ( i * 2 )] );
511 1053874 : r2 = L_msu0( r2, pFilter2[2 + ( p_stride * ( i * 2 ) )], pStates2[( 2 * L2 ) + ( i * 2 )] );
512 1053874 : r2 = L_msu0( r2, pFilter2[3 + ( p_stride * ( i * 2 ) )], pStates2[( 3 * L2 ) + ( i * 2 )] );
513 1053874 : r2 = L_msu0( r2, pFilter2[4 + ( p_stride * ( i * 2 ) )], pStates2[( 4 * L2 ) + ( i * 2 )] );
514 :
515 1053874 : i1 = L_msu0( 0, pFilter3[0 + ( p_stride * ( i * 2 ) )], pStates3[( 0 * L2 ) + ( i * 2 )] );
516 1053874 : i1 = L_msu0( i1, pFilter3[1 + ( p_stride * ( i * 2 ) )], pStates3[( 1 * L2 ) + ( i * 2 )] );
517 1053874 : i1 = L_msu0( i1, pFilter3[2 + ( p_stride * ( i * 2 ) )], pStates3[( 2 * L2 ) + ( i * 2 )] );
518 1053874 : i1 = L_msu0( i1, pFilter3[3 + ( p_stride * ( i * 2 ) )], pStates3[( 3 * L2 ) + ( i * 2 )] );
519 1053874 : i1 = L_msu0( i1, pFilter3[4 + ( p_stride * ( i * 2 ) )], pStates3[( 4 * L2 ) + ( i * 2 )] );
520 :
521 1053874 : i2 = L_msu0( 0, pFilter4[0 - ( p_stride * ( i * 2 ) )], pStates4[( 0 * L2 ) - ( i * 2 )] );
522 1053874 : i2 = L_msu0( i2, pFilter4[1 - ( p_stride * ( i * 2 ) )], pStates4[( 1 * L2 ) - ( i * 2 )] );
523 1053874 : i2 = L_msu0( i2, pFilter4[2 - ( p_stride * ( i * 2 ) )], pStates4[( 2 * L2 ) - ( i * 2 )] );
524 1053874 : i2 = L_msu0( i2, pFilter4[3 - ( p_stride * ( i * 2 ) )], pStates4[( 3 * L2 ) - ( i * 2 )] );
525 1053874 : i2 = L_msu0( i2, pFilter4[4 - ( p_stride * ( i * 2 ) )], pStates4[( 4 * L2 ) - ( i * 2 )] );
526 :
527 : /* folding */
528 1053874 : rBuffer[2 * i] = L_sub( r1, r2 );
529 1053874 : move32();
530 1053874 : rBuffer[( ( i * 2 ) + 1 )] = L_negate( L_add( i1, i2 ) );
531 1053874 : move32();
532 :
533 : /* folding */
534 1053874 : iBuffer[2 * i] = L_add( r1, r2 );
535 1053874 : move32();
536 1053874 : iBuffer[( ( i * 2 ) + 1 )] = L_sub( i1, i2 );
537 1053874 : move32();
538 : }
539 :
540 1188716 : FOR( i = M4; i < m2; i++ )
541 : {
542 : /* prototype filter */
543 1053874 : r1 = L_msu0( 0, pFilter1[0 - ( p_stride * ( i * 2 ) )], pStates1[( 0 * L2 ) - ( i * 2 )] );
544 1053874 : r1 = L_msu0( r1, pFilter1[1 - ( p_stride * ( i * 2 ) )], pStates1[( 1 * L2 ) - ( i * 2 )] );
545 1053874 : r1 = L_msu0( r1, pFilter1[2 - ( p_stride * ( i * 2 ) )], pStates1[( 2 * L2 ) - ( i * 2 )] );
546 1053874 : r1 = L_msu0( r1, pFilter1[3 - ( p_stride * ( i * 2 ) )], pStates1[( 3 * L2 ) - ( i * 2 )] );
547 1053874 : r1 = L_msu0( r1, pFilter1[4 - ( p_stride * ( i * 2 ) )], pStates1[( 4 * L2 ) - ( i * 2 )] );
548 :
549 1053874 : r2 = L_msu0( 0, pFilter6[0 + ( p_stride * ( i * 2 ) )], pStates6[( 0 * L2 ) + ( i * 2 )] );
550 1053874 : r2 = L_msu0( r2, pFilter6[1 + ( p_stride * ( i * 2 ) )], pStates6[( 1 * L2 ) + ( i * 2 )] );
551 1053874 : r2 = L_msu0( r2, pFilter6[2 + ( p_stride * ( i * 2 ) )], pStates6[( 2 * L2 ) + ( i * 2 )] );
552 1053874 : r2 = L_msu0( r2, pFilter6[3 + ( p_stride * ( i * 2 ) )], pStates6[( 3 * L2 ) + ( i * 2 )] );
553 1053874 : r2 = L_msu0( r2, pFilter6[4 + ( p_stride * ( i * 2 ) )], pStates6[( 4 * L2 ) + ( i * 2 )] );
554 :
555 1053874 : i1 = L_msu0( 0, pFilter5[0 - ( p_stride * ( i * 2 ) )], pStates5[( 0 * L2 ) - ( i * 2 )] );
556 1053874 : i1 = L_msu0( i1, pFilter5[1 - ( p_stride * ( i * 2 ) )], pStates5[( 1 * L2 ) - ( i * 2 )] );
557 1053874 : i1 = L_msu0( i1, pFilter5[2 - ( p_stride * ( i * 2 ) )], pStates5[( 2 * L2 ) - ( i * 2 )] );
558 1053874 : i1 = L_msu0( i1, pFilter5[3 - ( p_stride * ( i * 2 ) )], pStates5[( 3 * L2 ) - ( i * 2 )] );
559 1053874 : i1 = L_msu0( i1, pFilter5[4 - ( p_stride * ( i * 2 ) )], pStates5[( 4 * L2 ) - ( i * 2 )] );
560 :
561 1053874 : i2 = L_msu0( 0, pFilter3[0 + ( p_stride * ( i * 2 ) )], pStates3[( 0 * L2 ) + ( i * 2 )] );
562 1053874 : i2 = L_msu0( i2, pFilter3[1 + ( p_stride * ( i * 2 ) )], pStates3[( 1 * L2 ) + ( i * 2 )] );
563 1053874 : i2 = L_msu0( i2, pFilter3[2 + ( p_stride * ( i * 2 ) )], pStates3[( 2 * L2 ) + ( i * 2 )] );
564 1053874 : i2 = L_msu0( i2, pFilter3[3 + ( p_stride * ( i * 2 ) )], pStates3[( 3 * L2 ) + ( i * 2 )] );
565 1053874 : i2 = L_msu0( i2, pFilter3[4 + ( p_stride * ( i * 2 ) )], pStates3[( 4 * L2 ) + ( i * 2 )] );
566 :
567 : /* folding */
568 1053874 : rBuffer[2 * i] = L_add( r1, r2 );
569 1053874 : move32();
570 1053874 : rBuffer[( ( i * 2 ) + 1 )] = L_sub( i1, i2 );
571 1053874 : move32();
572 :
573 : /* folding */
574 1053874 : iBuffer[2 * i] = L_sub( r1, r2 );
575 1053874 : move32();
576 1053874 : iBuffer[( ( i * 2 ) + 1 )] = L_add( i1, i2 );
577 1053874 : move32();
578 : }
579 :
580 : /* pre modulation of DST IV and DCT IV */
581 134842 : calcModulation( &rBuffer[0], &rBuffer[1], &rBuffer[0], &rBuffer[1], 2, 2, 2, 2,
582 : &iBuffer[0], &iBuffer[1], &iBuffer[0], &iBuffer[1], 2, 2, 2, 2,
583 : rRotVctr, iRotVctr, m );
584 :
585 : /* FFT of DST IV */
586 134842 : scale = 0;
587 134842 : move16();
588 134842 : BASOP_cfft( (cmplx *) rBuffer, m2, &scale, workBuffer );
589 :
590 : /* store analysis scalefactor for cldfb */
591 134842 : scaleFactor->lb_scale = add( cldfbBank->anaScalefactor, add( cldfbBank->FilterStates_eg, scale ) );
592 134842 : move16();
593 :
594 : /* FFT of DCT IV */
595 134842 : BASOP_cfft( (cmplx *) iBuffer, m2, &scale, workBuffer );
596 :
597 : /* post modulation of DST IV and DCT IV */
598 134842 : calcModulation( &rAnalysis[k][m - 1], &rAnalysis[k][0], &rBuffer[0], &rBuffer[1], -2, 2, 2, 2,
599 134842 : &iAnalysis[k][0], &iAnalysis[k][m - 1], &iBuffer[0], &iBuffer[1], 2, -2, 2, 2,
600 : rRotVctr, iRotVctr, m );
601 :
602 :
603 : /* update states pointer */
604 134842 : pStates1 = &pStates1[cldfbBank->no_channels];
605 134842 : pStates2 = &pStates2[cldfbBank->no_channels];
606 134842 : pStates3 = &pStates3[cldfbBank->no_channels];
607 134842 : pStates5 = &pStates5[cldfbBank->no_channels];
608 134842 : pStates4 = &pStates4[cldfbBank->no_channels];
609 134842 : pStates6 = &pStates6[cldfbBank->no_channels];
610 : }
611 8490 : }
612 :
613 :
614 : /* cldfbSynthesis_fx
615 :
616 : Parameters:
617 : cldfbBank I/O: handle to analysis CLDFB filter struct
618 : **rAnalysis I: matrix holding the real part of the subband samples
619 : **iAnalysis I: matrix holding the imaginary part of the subband samples
620 : *scaleFactor I: pointer to cldfb scalefactor struct
621 : ov_len I: determines overlapping area in time slots (obsolete)
622 : *timeOut O: pointer to time domain data
623 : stride I: stride for time domain data
624 : *pWorkBuffer I: pointer to scratch buffer, needed for buffer of size 2*cldfbbands*Word32 + 2*cldfbbands*Word16
625 :
626 : Function:
627 : Performs inverse complex-valued subband filtering of the subband samples in rAnalysis and iAnalysis
628 : and stores the time domain data in timeOut
629 :
630 : Returns:
631 : void
632 : */
633 4052 : void cldfbSynthesis_fx(
634 : HANDLE_CLDFB_FILTER_BANK cldfbBank,
635 : Word32 **rAnalysis,
636 : Word32 **iAnalysis,
637 : const CLDFB_SCALE_FACTOR *scaleFactor,
638 : Word16 *timeOut, // Q(15-timeOut_e)
639 : const Word16 timeOut_e,
640 : const Word16 nTimeSlots,
641 : Word32 *pWorkBuffer // Qx
642 : )
643 : {
644 : Word16 i;
645 : Word16 k;
646 : Word16 L2;
647 : Word16 m;
648 : Word16 m2;
649 : Word16 Lz;
650 : Word16 Mz;
651 : Word32 acc;
652 : Word16 offset1;
653 : Word16 offset2;
654 : Word16 channels0;
655 : Word16 channels1;
656 : Word16 channels2;
657 : Word16 channels3;
658 : Word16 channels4;
659 : Word16 statesSizeM1;
660 : Word16 statesSizeM2;
661 : Word16 stride;
662 :
663 : Word16 scale, scaleMod;
664 : Word16 outScale;
665 : Word16 scaleLB;
666 : Word16 scaleHB;
667 :
668 : Word32 *rAnalysisS;
669 : Word32 *iAnalysisS;
670 :
671 : Word32 *rBuffer;
672 : Word32 *iBuffer;
673 : Word16 *nBuffer;
674 :
675 : Word16 *pStates;
676 : Word16 *pStatesI;
677 : Word16 *pStatesR;
678 :
679 : const Word16 *pFilterS;
680 : const Word16 *pFilterM;
681 :
682 : const Word16 *rRotVctr;
683 : const Word16 *iRotVctr;
684 : Word32 workBuffer[2 * BASOP_CFFT_MAX_LENGTH];
685 :
686 4052 : m = cldfbBank->no_channels;
687 4052 : move16();
688 4052 : L2 = shl( m, 1 );
689 4052 : m2 = shr( m, 1 );
690 4052 : Lz = s_min( cldfbBank->lsb, sub( m, cldfbBank->bandsToZero ) );
691 4052 : Mz = s_min( cldfbBank->usb, sub( m, cldfbBank->bandsToZero ) );
692 4052 : stride = 1; /* constant */
693 4052 : move16();
694 4052 : channels0 = sub( m, cldfbBank->zeros );
695 4052 : channels1 = sub( m, 1 );
696 4052 : channels2 = shl( m, 1 );
697 4052 : channels3 = add( m, channels2 );
698 4052 : channels4 = shl( channels2, 1 );
699 :
700 4052 : statesSizeM1 = sub( shl( cldfbBank->p_filter_length, 1 ), m );
701 4052 : statesSizeM2 = sub( statesSizeM1, m );
702 :
703 4052 : offset1 = sub( channels1, cldfbBank->zeros );
704 4052 : offset2 = add( offset1, cldfbBank->no_channels );
705 :
706 4052 : rBuffer = &pWorkBuffer[0];
707 4052 : iBuffer = &pWorkBuffer[m];
708 4052 : nBuffer = (Word16 *) ( &pWorkBuffer[L2] );
709 :
710 4052 : rAnalysisS = &pWorkBuffer[3 * m];
711 4052 : iAnalysisS = &pWorkBuffer[4 * m];
712 :
713 4052 : rRotVctr = cldfbBank->rRotVctr;
714 4052 : iRotVctr = cldfbBank->iRotVctr;
715 :
716 4052 : scale = scaleFactor->lb_scale;
717 4052 : move16();
718 4052 : if ( NE_16( Lz, Mz ) )
719 : {
720 1255 : scale = s_max( scale, scaleFactor->hb_scale );
721 : }
722 4052 : scaleLB = limitScale32( sub( scale, scaleFactor->lb_scale ) );
723 4052 : scaleHB = limitScale32( sub( scale, scaleFactor->hb_scale ) );
724 :
725 4052 : outScale = cldfbBank->synFilterHeadroom;
726 4052 : move16();
727 :
728 4052 : scaleMod = sub( add( scale, cldfbBank->outScalefactor ), outScale );
729 :
730 : /* Increase CLDFB synthesis states for low level signals */
731 4052 : IF( LT_16( scale, 8 ) )
732 : {
733 127 : scaleMod = add( scaleMod, 2 );
734 127 : outScale = sub( outScale, 2 );
735 : }
736 4052 : scaleMod = sub( scaleMod, timeOut_e );
737 4052 : scale = add( outScale, timeOut_e );
738 4052 : IF( NE_16( scale, cldfbBank->FilterStates_eg ) )
739 : {
740 505 : Scale_sig( cldfbBank->FilterStates, statesSizeM2, sub( cldfbBank->FilterStates_eg, scale ) ); // Q(15-scale)
741 505 : cldfbBank->FilterStates_eg = scale;
742 505 : move16();
743 : }
744 :
745 68644 : FOR( k = 0; k < nTimeSlots; k++ )
746 : {
747 : {
748 677876 : FOR( i = 0; i < Lz; i += 2 )
749 : {
750 613284 : rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleLB );
751 613284 : move32();
752 613284 : iAnalysisS[i] = L_negate( L_shr( iAnalysis[k][i], scaleLB ) );
753 613284 : move32();
754 : }
755 :
756 64592 : IF( LT_16( i, Mz ) )
757 : {
758 386418 : FOR( ; i < Mz; i += 2 )
759 : {
760 366408 : rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleHB );
761 366408 : move32();
762 366408 : iAnalysisS[i] = L_negate( L_shr( iAnalysis[k][i], scaleHB ) );
763 366408 : move32();
764 : }
765 : }
766 :
767 64592 : IF( LT_16( i, m ) )
768 : {
769 383518 : FOR( ; i < m; i += 2 )
770 : {
771 360648 : rAnalysisS[i] = 0;
772 360648 : move32();
773 360648 : iAnalysisS[i] = 0;
774 360648 : move32();
775 : }
776 : }
777 :
778 677876 : FOR( i = 1; i < Lz; i += 2 )
779 : {
780 613284 : rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleLB );
781 613284 : move32();
782 613284 : iAnalysisS[i] = L_shr( iAnalysis[k][i], scaleLB );
783 613284 : move32();
784 : }
785 :
786 64592 : IF( LT_16( i, Mz ) )
787 : {
788 386418 : FOR( ; i < Mz; i += 2 )
789 : {
790 366408 : rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleHB );
791 366408 : move32();
792 366408 : iAnalysisS[i] = L_shr( iAnalysis[k][i], scaleHB );
793 366408 : move32();
794 : }
795 : }
796 :
797 64592 : IF( LT_16( i, m ) )
798 : {
799 383518 : FOR( ; i < m; i += 2 )
800 : {
801 360648 : rAnalysisS[i] = 0;
802 360648 : move32();
803 360648 : iAnalysisS[i] = 0;
804 360648 : move32();
805 : }
806 : }
807 : }
808 :
809 : /* pre modulation */
810 64592 : calcModulation( &rBuffer[0], &rBuffer[1], &rAnalysisS[0], &rAnalysisS[m - 1], 2, 2, 2, -2,
811 64592 : &iBuffer[0], &iBuffer[1], &iAnalysisS[0], &iAnalysisS[m - 1], 2, 2, 2, -2,
812 : rRotVctr, iRotVctr, m );
813 :
814 :
815 : /* FFT of DST IV */
816 64592 : scale = 0;
817 64592 : move16();
818 64592 : BASOP_cfft( (cmplx *) rBuffer, m2, &scale, workBuffer );
819 :
820 : /* FFT of DCT IV */
821 64592 : scale = scaleMod;
822 64592 : move16();
823 64592 : BASOP_cfft( (cmplx *) iBuffer, m2, &scale, workBuffer );
824 :
825 : /* post modulation and folding */
826 64592 : calcModulationAndFolding( nBuffer, rBuffer, iBuffer, rRotVctr, iRotVctr, cldfbBank->synGain, scale, m, m2 );
827 :
828 : /* prototype filter */
829 64592 : pStates = &cldfbBank->FilterStates[( k * L2 )];
830 64592 : pFilterS = &cldfbBank->p_filter[0];
831 64592 : pFilterM = &cldfbBank->p_filter[shr( cldfbBank->p_filter_length, 1 )];
832 :
833 2745272 : FOR( i = 0; i < channels0; i++ )
834 : {
835 2680680 : pStatesI = &pStates[i];
836 2680680 : pStatesR = &pStates[add( i, channels3 )];
837 :
838 2680680 : acc = L_mult( *pStatesI, *pFilterS++ );
839 2680680 : acc = L_mac( acc, *pStatesR, *pFilterM++ );
840 2680680 : pStatesR += channels4;
841 2680680 : pStatesI += channels4;
842 :
843 2680680 : acc = L_mac( acc, *pStatesI, *pFilterS++ );
844 2680680 : acc = L_mac( acc, *pStatesR, *pFilterM++ );
845 2680680 : pStatesR += channels4;
846 2680680 : pStatesI += channels4;
847 :
848 2680680 : acc = L_mac( acc, *pStatesI, *pFilterS++ );
849 2680680 : acc = L_mac( acc, *pStatesR, *pFilterM++ );
850 2680680 : pStatesR += channels4;
851 2680680 : pStatesI += channels4;
852 :
853 2680680 : acc = L_mac( acc, *pStatesI, *pFilterS++ );
854 2680680 : acc = L_mac( acc, *pStatesR, *pFilterM++ );
855 2680680 : pStatesI += channels4;
856 :
857 2680680 : acc = L_mac( acc, *pStatesI, *pFilterS++ );
858 2680680 : acc = L_mac( acc, nBuffer[sub( channels1, i )], *pFilterM++ );
859 :
860 : BASOP_SATURATE_WARNING_OFF_EVS
861 2680680 : timeOut[( offset1 - i ) * stride] = round_fx_sat( L_shl_sat( acc, outScale ) );
862 : BASOP_SATURATE_WARNING_ON_EVS
863 2680680 : move16();
864 : }
865 :
866 64592 : FOR( ; i < cldfbBank->no_channels; i++ )
867 : {
868 0 : pStatesI = &pStates[i + channels2];
869 0 : pStatesR = &pStates[( i + channels2 ) + channels3];
870 :
871 0 : acc = L_mult( *pStatesI, *pFilterS++ );
872 0 : acc = L_mac( acc, *pStatesR, *pFilterM++ );
873 0 : pStatesR += channels4;
874 0 : pStatesI += channels4;
875 :
876 0 : acc = L_mac( acc, *pStatesI, *pFilterS++ );
877 0 : acc = L_mac( acc, *pStatesR, *pFilterM++ );
878 0 : pStatesR += channels4;
879 0 : pStatesI += channels4;
880 :
881 0 : acc = L_mac( acc, *pStatesI, *pFilterS++ );
882 0 : acc = L_mac( acc, *pStatesR, *pFilterM++ );
883 0 : pStatesR += channels4;
884 0 : pStatesI += channels4;
885 :
886 0 : acc = L_mac( acc, *pStatesI, *pFilterS++ );
887 0 : acc = L_mac( acc, *pStatesR, *pFilterM++ );
888 :
889 0 : acc = L_mac( acc, nBuffer[channels1 + m - i], *pFilterS++ );
890 0 : pFilterM++;
891 :
892 : BASOP_SATURATE_WARNING_OFF_EVS
893 0 : timeOut[( offset2 - i ) * stride] = round_fx_sat( L_shl_sat( acc, outScale ) );
894 : BASOP_SATURATE_WARNING_ON_EVS
895 0 : move16();
896 : }
897 :
898 2745272 : FOR( i = 0; i < cldfbBank->no_channels; i++ )
899 : {
900 2680680 : pStates[statesSizeM1 + i] = nBuffer[channels1 - i];
901 2680680 : move16();
902 2680680 : pStates[statesSizeM2 + i] = nBuffer[( channels1 + m ) - i];
903 2680680 : move16();
904 : }
905 :
906 64592 : timeOut = &timeOut[m * stride];
907 : }
908 :
909 : /* move filter states */
910 4052 : Copy( &cldfbBank->FilterStates[nTimeSlots * L2], cldfbBank->FilterStates, statesSizeM2 );
911 4052 : set16_fx( &cldfbBank->FilterStates[statesSizeM2], 0, L2 );
912 4052 : }
913 :
914 :
915 : /*-------------------------------------------------------------------*
916 : * configureClfdb()
917 : *
918 : * configures a CLDFB handle
919 : *--------------------------------------------------------------------*/
920 :
921 25 : void configureCldfb( HANDLE_CLDFB_FILTER_BANK h_cldfb, /*!< Returns handle */
922 : const Word16 no_channels, /*!< Number of channels (bands) */
923 : const Word16 frameSize /*!< FrameSize */
924 : )
925 : {
926 :
927 25 : h_cldfb->no_channels = no_channels;
928 25 : move16();
929 25 : assert( h_cldfb->no_channels >= 10 );
930 25 : h_cldfb->no_col = div_l( frameSize, shr( h_cldfb->no_channels, 1 ) );
931 25 : move16();
932 :
933 : /* was cldfbInitFilterBank()*/
934 25 : h_cldfb->anaScalefactor = 0;
935 25 : move16();
936 25 : h_cldfb->synScalefactor = 0;
937 25 : move16();
938 25 : h_cldfb->bandsToZero = 0;
939 25 : move16();
940 25 : h_cldfb->filtermode = 0;
941 25 : move16();
942 25 : h_cldfb->memory = 0;
943 25 : move16();
944 25 : h_cldfb->memory_length = 0;
945 25 : move16();
946 :
947 25 : h_cldfb->p_filter_length = i_mult( 10, h_cldfb->no_channels );
948 25 : move16();
949 :
950 25 : h_cldfb->flags = s_or( h_cldfb->flags, CLDFB_FLAG_2_5MS_SETUP );
951 25 : move16();
952 25 : h_cldfb->filterScale = CLDFB_CLDFB80_PFT_SCALE;
953 25 : move16();
954 :
955 25 : h_cldfb->zeros = 0;
956 25 : move16();
957 25 : h_cldfb->synFilterHeadroom = SYN_FILTER_HEADROOM_2_5MS;
958 25 : move16();
959 :
960 25 : cldfb_init_proto_and_twiddles( h_cldfb );
961 :
962 25 : h_cldfb->lsb = no_channels;
963 25 : move16();
964 25 : h_cldfb->usb = s_min( no_channels, h_cldfb->no_channels ); /* Does this make any sense? in the previous implemenatation lsb, usb and no_channels are all maxCldfbBands */
965 25 : move16();
966 :
967 25 : h_cldfb->FilterStates = (void *) h_cldfb->FilterStates;
968 25 : h_cldfb->outScalefactor = h_cldfb->synScalefactor;
969 25 : move16();
970 :
971 25 : return;
972 : }
973 :
974 : /*-------------------------------------------------------------------*
975 : * openClfdb()
976 : *
977 : * open and configures a CLDFB handle
978 : *--------------------------------------------------------------------*/
979 15 : ivas_error openCldfb(
980 : HANDLE_CLDFB_FILTER_BANK *h_cldfb, /*!< Returns handle */
981 : const Word16 type, /*!< analysis or synthesis */
982 : const Word16 maxCldfbBands, /*!< number of cldfb bands */
983 : const Word16 frameSize /*!< FrameSize */
984 : )
985 : {
986 : HANDLE_CLDFB_FILTER_BANK hs;
987 :
988 15 : hs = (HANDLE_CLDFB_FILTER_BANK) malloc( sizeof( CLDFB_FILTER_BANK ) );
989 15 : IF( hs == NULL )
990 : {
991 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" );
992 : }
993 :
994 15 : hs->type = type;
995 15 : move16();
996 :
997 15 : IF( type == CLDFB_ANALYSIS )
998 : {
999 9 : hs->FilterStates = (Word16 *) malloc( STATE_BUFFER_SIZE * maxCldfbBands * sizeof( Word16 ) );
1000 : }
1001 : ELSE
1002 : {
1003 6 : hs->FilterStates = (Word16 *) malloc( 2 * STATE_BUFFER_SIZE * maxCldfbBands * sizeof( Word16 ) );
1004 : }
1005 15 : if ( hs->FilterStates == NULL )
1006 : {
1007 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" );
1008 : }
1009 15 : hs->flags = s_and( hs->flags, ~CLDFB_FLAG_KEEP_STATES );
1010 15 : move16();
1011 15 : configureCldfb( hs, maxCldfbBands, frameSize );
1012 :
1013 15 : hs->memory = NULL;
1014 15 : hs->memory_length = 0;
1015 15 : move16();
1016 :
1017 15 : IF( hs->type == CLDFB_ANALYSIS )
1018 : {
1019 9 : test();
1020 9 : IF( ( s_and( hs->flags, CLDFB_FLAG_KEEP_STATES ) == 0 ) && ( hs->FilterStates != 0 ) )
1021 : {
1022 9 : set16_fx( hs->FilterStates, 0, i_mult( STATE_BUFFER_SIZE, hs->no_channels ) );
1023 9 : set16_fx( hs->FilterStates_e, 0, sizeof( hs->FilterStates_e ) / sizeof( hs->FilterStates_e[0] ) );
1024 :
1025 9 : hs->FilterStates_eg = 0;
1026 9 : move16();
1027 : }
1028 : }
1029 6 : ELSE IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
1030 : {
1031 6 : IF( hs->FilterStates != 0 )
1032 : {
1033 6 : IF( s_and( hs->flags, CLDFB_FLAG_KEEP_STATES ) == 0 )
1034 : {
1035 6 : set16_fx( hs->FilterStates, 0, i_mult( shl( STATE_BUFFER_SIZE, 1 ), hs->no_channels ) );
1036 : }
1037 : }
1038 6 : hs->FilterStates_eg = 0;
1039 6 : move16();
1040 : }
1041 :
1042 15 : if ( h_cldfb != NULL )
1043 : {
1044 15 : *h_cldfb = hs;
1045 : }
1046 :
1047 15 : return IVAS_ERR_OK;
1048 : }
1049 :
1050 :
1051 : /*-------------------------------------------------------------------*
1052 : * resampleCldfb()
1053 : *
1054 : * Change sample rate of filter bank
1055 : *--------------------------------------------------------------------*/
1056 10 : void resampleCldfb( HANDLE_CLDFB_FILTER_BANK hs,
1057 : const Word16 newCldfbBands,
1058 : const Word16 frameSize,
1059 : const Word8 firstFrame )
1060 :
1061 : {
1062 : Word16 timeOffset;
1063 : Word16 timeOffsetOld;
1064 : Word16 noChannelsOld;
1065 :
1066 10 : noChannelsOld = hs->no_channels;
1067 10 : move16();
1068 10 : timeOffsetOld = sub( sub( hs->p_filter_length, hs->no_channels ), hs->zeros );
1069 :
1070 : /* change all CLDFB bank parameters that depend on the no of channels */
1071 10 : hs->flags = s_or( hs->flags, CLDFB_FLAG_KEEP_STATES );
1072 10 : move16();
1073 :
1074 : /* new settings */
1075 10 : configureCldfb( hs, newCldfbBands, frameSize );
1076 :
1077 : /* resample cldfb state buffer */
1078 10 : timeOffset = sub( sub( hs->p_filter_length, hs->no_channels ), hs->zeros );
1079 :
1080 10 : IF( firstFrame == 0 )
1081 : {
1082 : /*low complexity-resampling only stored previous samples that are needed for next frame modulation */
1083 4 : lerp( hs->FilterStates + i_mult( noChannelsOld, hs->no_col ), hs->FilterStates + i_mult( noChannelsOld, hs->no_col ), timeOffset, timeOffsetOld );
1084 4 : Copy( hs->FilterStates + i_mult( noChannelsOld, hs->no_col ), hs->FilterStates + frameSize, timeOffset );
1085 : }
1086 :
1087 10 : return;
1088 : }
1089 :
1090 : /*
1091 : AnalysisPostSpectrumScaling_Fx
1092 :
1093 : Parameters:
1094 : cldfbBank I: CLDFB handle
1095 : **rSubband32 I: matrix holding real part of the CLDFB subsamples
1096 : **iSubband32 I: matrix holding imaginary part of the CLDFB subsamples
1097 : **rSubband16 O: matrix holding real part of the CLDFB subsamples
1098 : **iSubband16 O: matrix holding imaginary part of the CLDFB subsamples
1099 : *cldfbScale O: cldfb lowband scalefactor
1100 :
1101 : Function:
1102 : performs dynamic spectrum scaling for all subband
1103 :
1104 : Returns:
1105 : headroom
1106 : */
1107 : Word16
1108 397424 : AnalysisPostSpectrumScaling_Fx( HANDLE_CLDFB_FILTER_BANK cldfbBank, /*!< Handle of cldfbBank */
1109 : Word32 **rSubband32, /*!< Real bands Q(cldfbSacle)*/
1110 : Word32 **iSubband32, /*!< Imaginary bands Q(cldfbSacle)*/
1111 : Word16 **rSubband16, /*!< Real bands Q(cldfbSacle)*/
1112 : Word16 **iSubband16, /*!< Imaginary bands Q(cldfbScale)*/
1113 : Word16 *cldfbScale /*!< CLDFB lowband scalefactor */
1114 : )
1115 : {
1116 : Word16 i;
1117 : Word16 j;
1118 : Word16 headRoom;
1119 :
1120 :
1121 397424 : headRoom = BASOP_util_norm_l_dim2_cplx(
1122 : (const Word32 *const *) rSubband32,
1123 : (const Word32 *const *) iSubband32,
1124 : 0,
1125 397424 : cldfbBank->no_channels,
1126 : 0,
1127 397424 : cldfbBank->no_col );
1128 :
1129 6756208 : FOR( i = 0; i < cldfbBank->no_col; i++ )
1130 : {
1131 364294784 : FOR( j = 0; j < cldfbBank->no_channels; j++ )
1132 : {
1133 357936000 : rSubband16[i][j] = round_fx_sat( L_shl_sat( rSubband32[i][j], headRoom ) ); // Q(cldfbSacle_headRoom)
1134 357936000 : iSubband16[i][j] = round_fx_sat( L_shl_sat( iSubband32[i][j], headRoom ) ); // Q(cldfbSacle+headRoom)
1135 357936000 : move16();
1136 357936000 : move16();
1137 : }
1138 : }
1139 :
1140 397424 : *cldfbScale = add( *cldfbScale, headRoom );
1141 397424 : move16();
1142 :
1143 :
1144 397424 : return headRoom;
1145 : }
1146 :
1147 :
1148 : /*-------------------------------------------------------------------*
1149 : * analysisCLDFBEncoder()
1150 : *
1151 : * Encoder CLDFB analysis + energy stage
1152 : *--------------------------------------------------------------------*/
1153 :
1154 3100 : void analysisCldfbEncoder_fx(
1155 : Encoder_State *st_fx, /* i/o: encoder state structure */
1156 : const Word16 *timeIn, // Q15
1157 : Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
1158 : Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
1159 : Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], // Q(enerScale.lb_scale16)
1160 : Word16 imagBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], // Q(enerScale.lb_scale16)
1161 : Word32 enerBuffSum[CLDFB_NO_CHANNELS_MAX], // Q(31-enerBuffSum_exp)
1162 : Word16 *enerBuffSum_exp,
1163 : CLDFB_SCALE_FACTOR *scale )
1164 : {
1165 : Word16 i;
1166 : CLDFB_SCALE_FACTOR enerScale;
1167 : Word32 *ppBuf_Real[CLDFB_NO_COL_MAX];
1168 : Word32 *ppBuf_Imag[CLDFB_NO_COL_MAX];
1169 : Word16 *ppBuf_Real16[CLDFB_NO_COL_MAX];
1170 : Word16 *ppBuf_Imag16[CLDFB_NO_COL_MAX];
1171 : Word32 workBuffer[256];
1172 3100 : Word16 num_slots = 1;
1173 3100 : move16();
1174 :
1175 52700 : FOR( i = 0; i < CLDFB_NO_COL_MAX; i++ )
1176 : {
1177 49600 : ppBuf_Real[i] = &realBuffer[i][0];
1178 49600 : ppBuf_Imag[i] = &imagBuffer[i][0];
1179 49600 : ppBuf_Real16[i] = &realBuffer16[i][0];
1180 49600 : ppBuf_Imag16[i] = &imagBuffer16[i][0];
1181 : }
1182 :
1183 : /* perform analysis */
1184 3100 : cldfbAnalysis_fx( st_fx->cldfbAnaEnc, ppBuf_Real, ppBuf_Imag, scale, timeIn, 0, CLDFB_NO_COL_MAX, workBuffer );
1185 :
1186 3100 : enerScale.lb_scale = negate( scale->lb_scale );
1187 3100 : enerScale.lb_scale16 = negate( scale->lb_scale );
1188 3100 : move16();
1189 3100 : move16();
1190 :
1191 : /* get 16bit respresentation */
1192 3100 : AnalysisPostSpectrumScaling_Fx(
1193 : st_fx->cldfbAnaEnc,
1194 : ppBuf_Real,
1195 : ppBuf_Imag,
1196 : ppBuf_Real16,
1197 : ppBuf_Imag16,
1198 : &enerScale.lb_scale16 );
1199 :
1200 : /* get the energy */
1201 3100 : GetEnergyCldfb( &st_fx->energyCoreLookahead_Fx,
1202 : &st_fx->sf_energyCoreLookahead_Fx,
1203 : num_slots,
1204 : ppBuf_Real16,
1205 : ppBuf_Imag16,
1206 3100 : enerScale.lb_scale16,
1207 3100 : st_fx->cldfbAnaEnc->no_channels,
1208 3100 : st_fx->cldfbAnaEnc->no_col,
1209 : &st_fx->currEnergyHF_fx,
1210 : &st_fx->currEnergyHF_e_fx,
1211 : enerBuffSum,
1212 : enerBuffSum_exp,
1213 : st_fx->hTECEnc );
1214 :
1215 3100 : return;
1216 : }
1217 :
1218 397424 : void GetEnergyCldfb( Word32 *energyLookahead, /*!< o: Q(*sf_energyLookahead) | pointer to the result in the core look-ahead slot */
1219 : Word16 *sf_energyLookahead, /*!< o: pointer to the scalefactor of the result in the core look-ahead slot */
1220 : const Word16 numLookahead, /*!< i: Q0 the number of look-ahead time-slots */
1221 : Word16 **realValues, /*!< i: Q(sf_Values) | the real part of the CLDFB subsamples */
1222 : Word16 **imagValues, /*!< i: Q(sf_Values) | the imaginary part of the CLDFB subsamples */
1223 : Word16 sf_Values, /*!< i: scalefactor of the CLDFB subcamples - apply as a negated Exponent */
1224 : Word16 numberBands, /*!< i: Q0 | number of CLDFB bands */
1225 : Word16 numberCols, /*!< i: Q0 | number of CLDFB subsamples */
1226 : Word32 *energyHF, /*!< o: Q31 | pointer to HF energy */
1227 : Word16 *energyHF_Exp, /*!< o: pointer to exponent of HF energy */
1228 : Word32 *energyValuesSum, /*!< o: Q(2*sf_Values-4) | pointer to sum array of energy values, not initialized*/
1229 : Word16 *energyValuesSum_Exp, /*!< o: pointer to exponents of energyValuesSum, not initialized */
1230 : TEC_ENC_HANDLE hTecEnc )
1231 : {
1232 : Word16 j;
1233 : Word16 k;
1234 : Word16 s;
1235 : Word16 sm;
1236 : Word32 nrg;
1237 : Word16 numberColsL;
1238 : Word16 numberBandsM;
1239 : Word16 numberBandsM20;
1240 : Word32 energyValues[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
1241 : Word16 energyValuesSumE[CLDFB_NO_CHANNELS_MAX];
1242 : // Word16 freqTable[2] = {20, 40};
1243 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1244 397424 : Flag Overflow = 0;
1245 397424 : move32();
1246 : #endif
1247 :
1248 6756208 : FOR( k = 0; k < numberCols; k++ )
1249 : {
1250 364294784 : FOR( j = 0; j < numberBands; j++ )
1251 : {
1252 357936000 : nrg = L_mult0( realValues[k][j], realValues[k][j] ); // Q(2*sf_Values)
1253 357936000 : nrg = L_mac0( nrg, imagValues[k][j], imagValues[k][j] ); // Q(2*sf_Values)
1254 :
1255 357936000 : energyValues[k][j] = nrg;
1256 357936000 : move32();
1257 : }
1258 : }
1259 :
1260 397424 : IF( GE_16( numberBands, freqTable[1] ) && hTecEnc != NULL )
1261 : {
1262 : Word32 *tempEnergyValuesArry[CLDFB_NO_COL_MAX];
1263 : Word16 ScaleX2;
1264 3100 : assert( numberCols == CLDFB_NO_COL_MAX );
1265 52700 : FOR( j = 0; j < numberCols; j++ )
1266 : {
1267 49600 : tempEnergyValuesArry[j] = &energyValues[j][0];
1268 : }
1269 :
1270 3100 : ScaleX2 = shl( sf_Values, 1 );
1271 3100 : calcHiEnvLoBuff_Fix(
1272 : numberCols,
1273 : freqTable,
1274 : 1,
1275 : tempEnergyValuesArry,
1276 3100 : hTecEnc->loBuffer,
1277 3100 : hTecEnc->hiTempEnv,
1278 : ScaleX2 );
1279 : }
1280 :
1281 22768424 : FOR( j = 0; j < numberBands; j++ )
1282 : {
1283 22371000 : energyValuesSum[j] = 0;
1284 22371000 : move32();
1285 22371000 : energyValuesSumE[j] = 31;
1286 22371000 : move16();
1287 380307000 : FOR( k = 0; k < CLDFB_NO_COL_MAX; k++ )
1288 : {
1289 357936000 : nrg = L_shr_r( energyValues[k][j], sub( energyValuesSumE[j], 31 ) ); // Q(2*sf_Values - (energyValuesSumE[j]-31))
1290 357936000 : IF( LT_32( L_sub( maxWord32, nrg ), energyValuesSum[j] ) )
1291 : {
1292 990700 : energyValuesSumE[j] = add( energyValuesSumE[j], 1 );
1293 990700 : move16();
1294 990700 : energyValuesSum[j] = L_shr_r( energyValuesSum[j], 1 );
1295 990700 : move32();
1296 990700 : nrg = L_shr_r( energyValues[k][j], 1 );
1297 : }
1298 357936000 : energyValuesSum[j] = L_add( energyValuesSum[j], nrg );
1299 357936000 : move32();
1300 : }
1301 22371000 : test();
1302 22371000 : if ( j == 0 || GT_16( energyValuesSumE[j], *energyValuesSum_Exp ) )
1303 : {
1304 468909 : *energyValuesSum_Exp = energyValuesSumE[j];
1305 468909 : move16();
1306 : }
1307 : }
1308 22768424 : FOR( j = 0; j < numberBands; j++ )
1309 : {
1310 22371000 : energyValuesSum[j] = L_shr_r( energyValuesSum[j], sub( *energyValuesSum_Exp, energyValuesSumE[j] ) ); // Q(energyValuesSum_Exp - (2*sf_Values))
1311 22371000 : move32();
1312 : }
1313 397424 : *energyValuesSum_Exp = sub( *energyValuesSum_Exp, shl( sf_Values, 1 ) );
1314 397424 : move16();
1315 :
1316 397424 : IF( GT_16( numberBands, 20 ) )
1317 : {
1318 381329 : numberBandsM = s_min( numberBands, 40 );
1319 381329 : numberBandsM20 = sub( numberBandsM, 20 );
1320 :
1321 381329 : numberColsL = sub( numberCols, numLookahead );
1322 :
1323 : /* sum up CLDFB energy above 8 kHz */
1324 381329 : s = BASOP_util_norm_s_bands2shift( i_mult( numberColsL, numberBandsM20 ) );
1325 381329 : s = sub( s, 4 );
1326 381329 : nrg = 0;
1327 381329 : move32();
1328 6101264 : FOR( k = 0; k < numberColsL; k++ )
1329 : {
1330 120118635 : FOR( j = 20; j < numberBandsM; j++ )
1331 : {
1332 114398700 : nrg = L_add_o( nrg, L_shr_o( energyValues[k][j], s, &Overflow ), &Overflow );
1333 : }
1334 : }
1335 :
1336 381329 : s = sub( sub( shl( sf_Values, 1 ), 1 ), s );
1337 381329 : sm = sub( s_min( s, *sf_energyLookahead ), 1 );
1338 :
1339 381329 : *energyHF = L_add( L_shr( nrg, limitScale32( sub( s, sm ) ) ),
1340 381329 : L_shr( *energyLookahead, sub( *sf_energyLookahead, sm ) ) ); // Q(31-(-nm))
1341 381329 : move32();
1342 :
1343 381329 : *energyHF_Exp = negate( sm );
1344 381329 : move16();
1345 :
1346 : /* process look-ahead region */
1347 381329 : s = BASOP_util_norm_s_bands2shift( i_mult( numLookahead, numberBandsM20 ) );
1348 381329 : s = sub( s, 2 );
1349 381329 : nrg = 0;
1350 381329 : move32();
1351 762658 : FOR( k = numberColsL; k < numberCols; k++ )
1352 : {
1353 8007909 : FOR( j = 20; j < numberBandsM; j++ )
1354 : {
1355 7626580 : nrg = L_add_o( nrg, L_shr_o( energyValues[k][j], s, &Overflow ), &Overflow );
1356 : }
1357 : }
1358 :
1359 381329 : s = sub( shl( sf_Values, 1 ), s );
1360 381329 : sm = sub( s_min( s, 44 ), 1 );
1361 : BASOP_SATURATE_WARNING_OFF_EVS
1362 : /* nrg + 6.1e-5f => value 0x40000000, scale 44 */
1363 381329 : *energyLookahead = L_add_sat( L_shr_sat( nrg, sub( s, sm ) ),
1364 381329 : L_shr_sat( 0x40000000, s_max( -31, s_min( 31, sub( 44, sm ) ) ) ) );
1365 381329 : move32();
1366 : BASOP_SATURATE_WARNING_ON_EVS
1367 381329 : *sf_energyLookahead = sm;
1368 381329 : move16();
1369 :
1370 381329 : return;
1371 : }
1372 :
1373 :
1374 16095 : *energyHF = 0x40000000;
1375 16095 : move32();
1376 16095 : *energyHF_Exp = 17;
1377 16095 : move16();
1378 : }
1379 :
1380 :
1381 : Word16
1382 20 : CLDFB_getNumChannels( Word32 sampleRate )
1383 : {
1384 :
1385 20 : Word16 nChannels = 0;
1386 20 : move16();
1387 :
1388 :
1389 20 : SWITCH( sampleRate )
1390 : {
1391 7 : case 48000:
1392 7 : move16();
1393 7 : nChannels = 60;
1394 7 : BREAK;
1395 2 : case 32000:
1396 2 : move16();
1397 2 : nChannels = 40;
1398 2 : BREAK;
1399 0 : case 25600:
1400 0 : move16();
1401 0 : nChannels = 32;
1402 0 : BREAK;
1403 8 : case 16000:
1404 8 : move16();
1405 8 : nChannels = 20;
1406 8 : BREAK;
1407 3 : case 12800:
1408 3 : move16();
1409 3 : nChannels = 16;
1410 3 : BREAK;
1411 0 : case 8000:
1412 0 : move16();
1413 0 : nChannels = 10;
1414 0 : BREAK;
1415 : }
1416 :
1417 20 : return ( nChannels );
1418 : }
1419 :
1420 : /*-------------------------------------------------------------------*
1421 : * cldfb_get_memory_length()
1422 : *
1423 : * Return length of filter state for recovery
1424 : *--------------------------------------------------------------------*/
1425 : static Word16
1426 285 : cldfb_get_memory_length( HANDLE_CLDFB_FILTER_BANK hs )
1427 : {
1428 285 : IF( EQ_16( hs->type, CLDFB_ANALYSIS ) )
1429 : {
1430 190 : return ( i_mult( hs->no_channels, STATE_BUFFER_SIZE ) );
1431 : }
1432 : ELSE
1433 : {
1434 95 : return ( i_mult( hs->no_channels, ( 9 * 2 ) ) );
1435 : }
1436 : }
1437 :
1438 : /*-------------------------------------------------------------------*
1439 : * GetEnergyCldfb()
1440 : *
1441 : * Remove handle
1442 : *--------------------------------------------------------------------*/
1443 15 : void deleteCldfb( HANDLE_CLDFB_FILTER_BANK *h_cldfb ) /* i: cldfb handle */
1444 : {
1445 15 : IF( *h_cldfb != NULL )
1446 : {
1447 15 : IF( ( *h_cldfb )->FilterStates != NULL )
1448 : {
1449 15 : free( ( *h_cldfb )->FilterStates );
1450 : }
1451 15 : free( *h_cldfb );
1452 : }
1453 15 : *h_cldfb = NULL;
1454 15 : }
1455 :
1456 :
1457 : /*-------------------------------------------------------------------*
1458 : * cldfb_init_proto_and_twiddles()
1459 : *
1460 : * Initializes rom pointer
1461 : *--------------------------------------------------------------------*/
1462 : static void
1463 25 : cldfb_init_proto_and_twiddles( HANDLE_CLDFB_FILTER_BANK hs ) /* i: cldfb handle */
1464 : {
1465 :
1466 : /*find appropriate set of rotVecs*/
1467 25 : SWITCH( hs->no_channels )
1468 : {
1469 0 : case 10:
1470 :
1471 0 : hs->rRotVctr = rRotVectr_10;
1472 0 : hs->iRotVctr = iRotVectr_10;
1473 0 : hs->synGain = cldfb_synGain[0];
1474 0 : move16();
1475 0 : hs->p_filter = cldfb_protoFilter_2_5ms[0];
1476 0 : hs->scale = cldfb_scale_2_5ms[0];
1477 0 : move16();
1478 0 : IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
1479 : {
1480 0 : hs->synScalefactor = add( cldfb_synScale[0], hs->filterScale );
1481 0 : move16();
1482 : }
1483 : ELSE
1484 : {
1485 0 : hs->anaScalefactor = add( cldfb_anaScale[0], hs->filterScale );
1486 0 : move16();
1487 : }
1488 0 : BREAK;
1489 :
1490 6 : case 16:
1491 6 : hs->rRotVctr = rRotVectr_16;
1492 6 : hs->iRotVctr = iRotVectr_16;
1493 6 : hs->synGain = cldfb_synGain[1];
1494 6 : move16();
1495 6 : hs->p_filter = cldfb_protoFilter_2_5ms[1];
1496 6 : hs->scale = cldfb_scale_2_5ms[1];
1497 6 : move16();
1498 : {
1499 6 : hs->anaScalefactor = add( cldfb_anaScale[1], hs->filterScale );
1500 6 : move16();
1501 : }
1502 6 : BREAK;
1503 :
1504 10 : case 20:
1505 10 : hs->rRotVctr = rRotVectr_20;
1506 10 : hs->iRotVctr = iRotVectr_20;
1507 10 : hs->synGain = cldfb_synGain[2];
1508 10 : move16();
1509 10 : hs->p_filter = cldfb_protoFilter_2_5ms[2];
1510 10 : hs->scale = cldfb_scale_2_5ms[2];
1511 10 : move16();
1512 10 : IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
1513 : {
1514 3 : hs->synScalefactor = add( cldfb_synScale[2], hs->filterScale );
1515 3 : move16();
1516 : }
1517 : ELSE
1518 : {
1519 7 : hs->anaScalefactor = add( cldfb_anaScale[2], hs->filterScale );
1520 7 : move16();
1521 : }
1522 10 : BREAK;
1523 :
1524 0 : case 32:
1525 0 : hs->rRotVctr = rRotVectr_32;
1526 0 : hs->iRotVctr = iRotVectr_32;
1527 0 : hs->synGain = cldfb_synGain[3];
1528 0 : move16();
1529 0 : hs->p_filter = cldfb_protoFilter_2_5ms[3];
1530 0 : hs->scale = cldfb_scale_2_5ms[3];
1531 0 : move16();
1532 : {
1533 0 : hs->anaScalefactor = add( cldfb_anaScale[3], hs->filterScale );
1534 0 : move16();
1535 : }
1536 0 : BREAK;
1537 :
1538 2 : case 40:
1539 2 : hs->rRotVctr = rRotVectr_40;
1540 2 : hs->iRotVctr = iRotVectr_40;
1541 2 : hs->synGain = cldfb_synGain[4];
1542 2 : move16();
1543 2 : hs->p_filter = cldfb_protoFilter_2_5ms[4];
1544 2 : hs->scale = cldfb_scale_2_5ms[4];
1545 2 : move16();
1546 2 : IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
1547 : {
1548 1 : hs->synScalefactor = add( cldfb_synScale[4], hs->filterScale );
1549 1 : move16();
1550 : }
1551 : ELSE
1552 : {
1553 1 : hs->anaScalefactor = add( cldfb_anaScale[4], hs->filterScale );
1554 1 : move16();
1555 : }
1556 2 : BREAK;
1557 :
1558 7 : case 60:
1559 7 : hs->rRotVctr = rRotVectr_60;
1560 7 : hs->iRotVctr = iRotVectr_60;
1561 7 : hs->synGain = cldfb_synGain[5];
1562 7 : move16();
1563 7 : hs->p_filter = cldfb_protoFilter_2_5ms[5];
1564 7 : hs->scale = cldfb_scale_2_5ms[5];
1565 7 : move16();
1566 7 : IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
1567 : {
1568 2 : hs->synScalefactor = add( cldfb_synScale[5], hs->filterScale );
1569 2 : move16();
1570 : }
1571 : ELSE
1572 : {
1573 5 : hs->anaScalefactor = add( cldfb_anaScale[5], hs->filterScale );
1574 5 : move16();
1575 : }
1576 7 : BREAK;
1577 : }
1578 25 : }
1579 :
1580 :
1581 : #define CLDFB_MEM_EXPONENTS ( CLDFB_NO_COL_MAX + 9 )
1582 :
1583 : /*-------------------------------------------------------------------*
1584 : * cldfb_save_memory()
1585 : *
1586 : * Save the memory of filter; to be restored with cldfb_restore_memory()
1587 : *--------------------------------------------------------------------*/
1588 : ivas_error
1589 72 : cldfb_save_memory( HANDLE_CLDFB_FILTER_BANK hs ) /* i: cldfb handle */
1590 : {
1591 72 : test();
1592 72 : IF( hs->memory != NULL || hs->memory_length != 0 )
1593 : {
1594 : /* memory already stored; Free memory first */
1595 0 : return IVAS_ERR_OK;
1596 : }
1597 72 : hs->memory_length = cldfb_get_memory_length( hs );
1598 72 : move16();
1599 72 : hs->memory = (Word16 *) calloc( hs->memory_length + CLDFB_MEM_EXPONENTS + 1, sizeof( Word16 ) );
1600 :
1601 : /* save the memory */
1602 72 : Copy( hs->FilterStates, hs->memory, hs->memory_length );
1603 72 : Copy( hs->FilterStates_e, hs->memory + hs->memory_length, CLDFB_MEM_EXPONENTS );
1604 72 : hs->memory[hs->memory_length + CLDFB_MEM_EXPONENTS] = hs->FilterStates_eg;
1605 72 : move16();
1606 72 : IF( hs->memory == NULL )
1607 : {
1608 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CLDFB\n" );
1609 : }
1610 72 : return IVAS_ERR_OK;
1611 : }
1612 :
1613 :
1614 : /*-------------------------------------------------------------------*
1615 : * cldfb_restore_memory()
1616 : *
1617 : * Restores the memory of filter; memory to be save by cldfb_save_memory()
1618 : *--------------------------------------------------------------------*/
1619 72 : void cldfb_restore_memory( HANDLE_CLDFB_FILTER_BANK hs ) /* i/o: cldfb handle */
1620 :
1621 : {
1622 : Word16 size;
1623 :
1624 :
1625 72 : size = cldfb_get_memory_length( hs );
1626 :
1627 : /* read the memory */
1628 72 : Copy( hs->memory, hs->FilterStates, hs->memory_length );
1629 72 : Copy( hs->memory + hs->memory_length, hs->FilterStates_e, CLDFB_MEM_EXPONENTS );
1630 72 : hs->FilterStates_eg = hs->memory[hs->memory_length + CLDFB_MEM_EXPONENTS];
1631 72 : move16();
1632 :
1633 :
1634 : /* adjust sample rate if it was changed in the meanwhile */
1635 72 : IF( NE_16( hs->memory_length, size ) )
1636 : {
1637 0 : lerp( hs->FilterStates, hs->FilterStates, size, hs->memory_length );
1638 : }
1639 :
1640 72 : hs->memory_length = 0;
1641 72 : free( hs->memory );
1642 72 : hs->memory = NULL;
1643 :
1644 72 : return;
1645 : }
1646 :
1647 : /*-------------------------------------------------------------------*
1648 : * cldfb_reset_memory()
1649 : *
1650 : * Resets the memory of filter.
1651 : *--------------------------------------------------------------------*/
1652 141 : void cldfb_reset_memory( HANDLE_CLDFB_FILTER_BANK hs ) /* i/o: cldfb handle */
1653 : {
1654 : Word16 length;
1655 :
1656 141 : length = cldfb_get_memory_length( hs );
1657 : /* erase the memory */
1658 141 : set16_fx( hs->FilterStates, 0, length );
1659 141 : set16_fx( hs->FilterStates_e, 0, sizeof( hs->FilterStates_e ) / sizeof( hs->FilterStates_e[0] ) );
1660 141 : hs->FilterStates_eg = 0;
1661 141 : move16();
1662 141 : return;
1663 : }
|