Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : /*====================================================================================
34 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
35 : ====================================================================================*/
36 :
37 : #include <stdint.h>
38 : #include <math.h>
39 : #include "options.h"
40 : #include "prot_fx.h"
41 : #include "wmc_auto.h"
42 :
43 : #define HP20_COEFF_SCALE ( 2 )
44 : #define HP20_FX_COEFF_SCALE ( 1 )
45 : /*
46 : * hp20
47 : *
48 : * Function:
49 : * 2nd order high pass filter with nominal cut off frequency at 20 Hz.
50 : *
51 : * Returns:
52 : * void
53 : */
54 :
55 27617100 : static Word32 HP50_Mode2_Mpy_32_16_fix( Word32 a, Word16 b )
56 : {
57 27617100 : Word32 result = Mpy_32_16_1( a, b );
58 : /* perform rounding towards lower value for negative results */
59 27617100 : if ( result < 0 )
60 13666982 : result = L_add( result, 1 );
61 27617100 : return result;
62 : }
63 :
64 18462900 : static Word32 HP50_Mpy_32_32_fix( Word32 a, Word32 b )
65 : {
66 18462900 : Word32 result = Mpy_32_32( a, b );
67 : /* perform rounding towards lower value for negative results */
68 18462900 : if ( result < 0 )
69 9229014 : result = L_add( result, 1 );
70 18462900 : return result;
71 : }
72 :
73 :
74 10300 : static void filter_2nd_order(
75 : Word16 signal[],
76 : const Word16 stride,
77 : const Word16 prescale,
78 : const Word16 lg,
79 : Word32 mem[4],
80 : Word32 a1,
81 : Word32 a2,
82 : Word32 b1,
83 : Word32 b2 )
84 : {
85 :
86 : Word16 i;
87 : Word16 x2, x1;
88 : Word32 L_sum, L_y1, L_y2;
89 :
90 : /*
91 : * Saturation: The states of the filter, namely L_y1 and L_y2 shall
92 : * never saturate, because that causes error in the filter feedback.
93 : * The final output written into signal[] might saturate because of
94 : * unavoidable filter overshoot.
95 : */
96 :
97 : /* Execute first 2 iterations with 32-bit x anx y memory values */
98 : BASOP_SATURATE_ERROR_ON_EVS
99 10300 : L_sum = HP50_Mpy_32_32_fix( b2, mem[2] ); /* b2*x2 */
100 10300 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( b1, mem[3] ) ); /* b1*x1 */
101 10300 : x2 = shr( signal[0], prescale );
102 10300 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x2 ) ); /* b2*x0 */
103 10300 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( mem[0], a2 ) ); /* y2*a2 */
104 10300 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( mem[1], a1 ) ); /* y1*a1 */
105 :
106 10300 : L_y2 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
107 : BASOP_SATURATE_ERROR_OFF_EVS
108 : BASOP_SATURATE_WARNING_OFF_EVS
109 10300 : signal[0] = round_fx_sat( L_shl_sat( L_y2, prescale ) );
110 :
111 : BASOP_SATURATE_WARNING_ON_EVS
112 :
113 : BASOP_SATURATE_ERROR_ON_EVS
114 10300 : L_sum = HP50_Mpy_32_32_fix( b2, mem[3] ); /* b2*x2 */
115 10300 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b1, x2 ) ); /* b1*x1 */
116 10300 : x1 = shr( signal[stride], prescale );
117 10300 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x1 ) ); /* b2*x0 */
118 10300 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( mem[1], a2 ) ); /* y2*a2 */
119 10300 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y2, a1 ) ); /* y1*a1 */
120 :
121 10300 : L_y1 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
122 : BASOP_SATURATE_ERROR_OFF_EVS
123 : BASOP_SATURATE_WARNING_OFF_EVS
124 10300 : signal[stride] = round_fx_sat( L_shl_sat( L_y1, prescale ) );
125 : BASOP_SATURATE_WARNING_ON_EVS
126 10300 : move16();
127 :
128 : /* New we use a trick and toggle x1/x2 and L_y1/L_y2 to save a few cycles unrolling the loop by 2 */
129 4608000 : FOR( i = 2; i < lg; i += 2 )
130 : {
131 : /* y[i+0] = b2*x[i-2] + b1*x[i-1] + b2*x[i-0] + a2*y[i-2] + a1*y[i-1]; */
132 : BASOP_SATURATE_ERROR_ON_EVS
133 4597700 : L_sum = HP50_Mode2_Mpy_32_16_fix( b2, x2 );
134 4597700 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b1, x1 ) );
135 4597700 : x2 = shr( signal[i * stride], prescale );
136 4597700 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x2 ) );
137 4597700 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y2, a2 ) );
138 4597700 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y1, a1 ) );
139 :
140 4597700 : L_y2 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
141 : BASOP_SATURATE_ERROR_OFF_EVS
142 : BASOP_SATURATE_WARNING_OFF_EVS
143 4597700 : signal[i_mult( i, stride )] = round_fx_sat( L_shl_sat( L_y2, prescale ) );
144 : BASOP_SATURATE_WARNING_ON_EVS
145 : /* y[i+1] = b2*x[i-1] + b1*x[i-0] + b2*x[i+1] + a2*y[i-1] + a1*y[i+0]; */
146 : BASOP_SATURATE_ERROR_ON_EVS
147 4597700 : L_sum = HP50_Mode2_Mpy_32_16_fix( b2, x1 );
148 4597700 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b1, x2 ) );
149 4597700 : x1 = shr( signal[( i + 1 ) * stride], prescale );
150 4597700 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x1 ) );
151 4597700 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y1, a2 ) );
152 4597700 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y2, a1 ) );
153 :
154 4597700 : L_y1 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
155 : BASOP_SATURATE_ERROR_OFF_EVS
156 : BASOP_SATURATE_WARNING_OFF_EVS
157 4597700 : signal[i_mult( add( i, 1 ), stride )] = round_fx_sat( L_shl_sat( L_y1, prescale ) );
158 : BASOP_SATURATE_WARNING_ON_EVS
159 4597700 : move16();
160 : }
161 : /* update static filter memory from variables */
162 10300 : mem[0] = L_y2;
163 10300 : move32();
164 10300 : mem[1] = L_y1;
165 10300 : move32();
166 10300 : mem[2] = L_deposit_h( x2 );
167 10300 : move32();
168 10300 : mem[3] = L_deposit_h( x1 );
169 10300 : move32();
170 :
171 :
172 10300 : return;
173 : }
174 :
175 :
176 10300 : void hp20( Word16 signal[], /* i/o: signal to filter any */
177 : const Word16 stride, /* i : stride to be applied accessing signal */
178 : const Word16 lg, /* i : length of signal (integer) Q0 */
179 : Word32 mem[5], /* i/o: static filter memory with this layout: */
180 : /* mem[0]: y[-2] (32-bit) */
181 : /* mem[1]; y[-1] (32-bit) */
182 : /* mem[2]: x[-2] << 16 */
183 : /* mem[3]: x[-1] << 16 */
184 : /* Note: mem[0..3] need to be scaled per frame */
185 : /* mem[4]: states scale */
186 : const Word32 sFreq ) /* i : input sampling rate Q0 */
187 : {
188 : Word32 a1, b1, a2, b2;
189 : Word16 prescale, prescaleOld, diff;
190 :
191 10300 : prescale = getScaleFactor16( signal, lg );
192 10300 : prescaleOld = extract_l( mem[4] );
193 10300 : diff = norm_l( L_shl_sat( mem[2], prescaleOld ) );
194 10300 : if ( mem[2] != 0 )
195 : {
196 10240 : prescale = s_min( prescale, diff );
197 : }
198 10300 : diff = norm_l( L_shl_sat( mem[3], prescaleOld ) );
199 10300 : if ( mem[3] != 0 )
200 : {
201 10235 : prescale = s_min( prescale, diff );
202 : }
203 : /* Take into account the left shift performed into the loop + 1 bit headroom*/
204 10300 : prescale = s_max( -12, sub( 1 + HP20_COEFF_SCALE, prescale ) );
205 10300 : IF( prescale != prescaleOld )
206 : {
207 4269 : diff = sub( prescale, prescaleOld );
208 4269 : mem[0] = L_shr_sat( mem[0], diff );
209 4269 : move32();
210 4269 : mem[1] = L_shr_sat( mem[1], diff );
211 4269 : move32();
212 4269 : mem[2] = L_shr_sat( mem[2], diff );
213 4269 : move32();
214 4269 : mem[3] = L_shr_sat( mem[3], diff ); //?sat
215 4269 : move32();
216 4269 : mem[4] = L_deposit_l( prescale );
217 : }
218 :
219 10300 : IF( EQ_32( sFreq, 8000 ) )
220 : {
221 : /* hp filter 20Hz at 3dB for 8000 Hz input sampling rate
222 : [b,a] = butter(2, 20.0/4000.0, 'high');
223 : b = [0.988954248067140 -1.977908496134280 0.988954248067140]
224 : a = [1.000000000000000 -1.977786483776764 0.978030508491796]*/
225 0 : a1 = 1061816033l /* 1.977786483776764 Q29*/;
226 0 : move32();
227 0 : a2 = -525076131l /*-0.978030508491796 Q29*/;
228 0 : move32();
229 0 : b1 = -1061881538l /*-1.977908496134280 Q29*/;
230 0 : move32();
231 0 : b2 = 530940769l /* 0.988954248067140 Q29*/;
232 0 : move32();
233 : }
234 10300 : ELSE IF( EQ_32( sFreq, 16000 ) )
235 : {
236 : /* hp filter 20Hz at 3dB for 16000KHz sampling rate
237 : [b,a] = butter(2, 20.0/8000.0, 'high');
238 : b = [0.994461788958195 -1.988923577916390 0.994461788958195]
239 : a = [1.000000000000000 -1.988892905899653 0.988954249933127] */
240 0 : a1 = 1067778748l /* 1.988892905899653 Q29*/;
241 0 : move32();
242 0 : a2 = -530940770l /*-0.988954249933127 Q29*/;
243 0 : move32();
244 0 : b1 = -1067795215l /*-1.988923577916390 Q29*/;
245 0 : move32();
246 0 : b2 = 533897608l /* 0.994461788958195 Q29*/;
247 0 : move32();
248 : }
249 10300 : ELSE IF( EQ_32( sFreq, 32000 ) )
250 : {
251 : /* hp filter 20Hz at 3dB for 32000KHz sampling rate
252 : [b,a] = butter(2, 20.0/16000.0, 'high');
253 : b = [0.997227049904470 -1.994454099808940 0.997227049904470]
254 : a = [1.000000000000000 -1.994446410541927 0.994461789075954]*/
255 2100 : a1 = 1070760263l /* 1.994446410541927 Q29*/;
256 2100 : move32();
257 2100 : a2 = -533897608l /*-0.994461789075954 Q29*/;
258 2100 : move32();
259 2100 : b1 = -1070764392l /*-1.994454099808940 Q29*/;
260 2100 : move32();
261 2100 : b2 = 535382196l /* 0.997227049904470 Q29*/;
262 2100 : move32();
263 : }
264 : ELSE
265 : {
266 8200 : assert( sFreq == 48000 );
267 : /* hp filter 20Hz at 3dB for 48000KHz sampling rate
268 : [b,a] = butter(2, 20.0/24000.0, 'high');
269 : b =[0.998150511190452 -1.996301022380904 0.998150511190452]
270 : a =[1.000000000000000 -1.996297601769122 0.996304442992686]*/
271 8200 : a1 = 1071754114l /* 1.996297601769122 Q29*/;
272 8200 : move32();
273 8200 : a2 = -534886875l /*-0.996304442992686 Q29*/;
274 8200 : move32();
275 8200 : b1 = -1071755951l /*-1.996301022380904 Q29*/;
276 8200 : move32();
277 8200 : b2 = 535877975l /* 0.998150511190452 Q29*/;
278 8200 : move32();
279 : }
280 :
281 :
282 10300 : filter_2nd_order( signal, stride, prescale, lg,
283 : mem, a1, a2, b1, b2 );
284 :
285 10300 : return;
286 : }
287 :
288 :
289 3304861 : void hp20_fx_32_opt(
290 : Word32 signal_fx[],
291 : const Word16 lg,
292 : Word32 mem_fx[],
293 : const Word32 Fs )
294 : {
295 : Word32 i;
296 : Word32 a1_fx, a2_fx, b1_fx, b2_fx;
297 : Word16 prescale, prescaleOld, prescale_current_frame, diff;
298 : Word32 tmp_mem[4];
299 :
300 3304861 : prescale = L_norm_arr( signal_fx, lg );
301 3304861 : prescale_current_frame = sub( 1 + HP20_FX_COEFF_SCALE, prescale );
302 :
303 3304861 : prescaleOld = extract_l( mem_fx[4] );
304 :
305 3304861 : tmp_mem[0] = L_shl_sat( mem_fx[0], prescaleOld );
306 3304861 : tmp_mem[1] = L_shl_sat( mem_fx[1], prescaleOld );
307 3304861 : tmp_mem[2] = L_shl_sat( mem_fx[2], prescaleOld );
308 3304861 : tmp_mem[3] = L_shl_sat( mem_fx[3], prescaleOld );
309 3304861 : move32();
310 3304861 : move32();
311 3304861 : move32();
312 3304861 : move32();
313 :
314 3304861 : diff = L_norm_arr( tmp_mem, 4 );
315 :
316 3304861 : prescale = s_min( prescale, diff );
317 :
318 3304861 : prescale = sub( 1 + HP20_FX_COEFF_SCALE, prescale );
319 : #ifdef FIX_2086_ENABLE_HP20_OPT_FOR_ENC
320 6547650 : if ( EQ_16( prescale_current_frame, 1 + HP20_FX_COEFF_SCALE - 31 ) || // signal_fx buffer contains only zeros, so use the mem_fx scale_factor instead
321 3242789 : LT_16( prescale_current_frame, prescale ) ) // To avoid overflow in the subsequent shr() scaling for W_y1, W_y2, x2, and x1 calculations before the for loop.
322 : #else
323 : if ( EQ_16( prescale_current_frame, 1 + HP20_FX_COEFF_SCALE - 31 ) ) // signal_fx buffer contains only zeros, so use the mem_fx scale_factor instead
324 : #endif
325 : {
326 78967 : prescale_current_frame = prescale;
327 : }
328 :
329 3304861 : diff = sub( prescale, prescaleOld );
330 3304861 : mem_fx[0] = L_shr_sat( mem_fx[0], diff );
331 3304861 : mem_fx[1] = L_shr_sat( mem_fx[1], diff );
332 3304861 : mem_fx[2] = L_shr_sat( mem_fx[2], diff );
333 3304861 : mem_fx[3] = L_shr_sat( mem_fx[3], diff );
334 3304861 : move32();
335 3304861 : move32();
336 3304861 : move32();
337 3304861 : move32();
338 3304861 : mem_fx[4] = L_deposit_l( prescale_current_frame );
339 3304861 : move32();
340 :
341 3304861 : IF( EQ_32( Fs, 8000 ) )
342 : {
343 : /* hp filter 20Hz at 3dB for 8000KHz input sampling rate
344 : [b,a] = butter(2, 20.0/4000.0, 'high');
345 : b = [0.988954248067140 -1.977908496134280 0.988954248067140]
346 : a =[1.000000000000000 -1.977786483776764 0.978030508491796]*/
347 0 : a1_fx = 2123632067 /* 1.977786483776764 Q30*/;
348 0 : a2_fx = -1050152262 /*-0.978030508491796 Q30*/;
349 0 : b1_fx = -2123763076 /*-1.977908496134280 Q30*/;
350 0 : b2_fx = 1061881538 /* 0.988954248067140 Q30*/;
351 : }
352 3304861 : ELSE IF( EQ_32( Fs, 16000 ) )
353 : {
354 : /* hp filter 20Hz at 3dB for 16000KHz sampling rate
355 : [b,a] = butter(2, 20.0/8000.0, 'high');
356 : b =[ 0.994461788958195 -1.988923577916390 0.994461788958195]
357 : a =[1.000000000000000 -1.988892905899653 0.988954249933127] */
358 210170 : a1_fx = 2135557497 /* 1.988892905899653 Q30*/;
359 210170 : a2_fx = -1061881540 /*-0.988954249933127 Q30*/;
360 210170 : b1_fx = -2135590430 /*-1.988923577916390 Q30*/;
361 210170 : b2_fx = 1067795215 /* 0.994461788958195 Q30*/;
362 : }
363 3094691 : ELSE IF( EQ_32( Fs, 32000 ) )
364 : {
365 : /* hp filter 20Hz at 3dB for 32000KHz sampling rate
366 : [b,a] = butter(2, 20.0/16000.0, 'high');
367 : b =[0.997227049904470 -1.994454099808940 0.997227049904470]
368 : a =[1.000000000000000 -1.994446410541927 0.994461789075954]*/
369 657188 : a1_fx = 2141520527 /* 1.994446410541927 Q30*/;
370 657188 : a2_fx = -1067795215 /*-0.994461789075954 Q30*/;
371 657188 : b1_fx = -2141528783 /*-1.994454099808940 Q30*/;
372 657188 : b2_fx = 1070764392 /* 0.997227049904470 Q30*/;
373 : }
374 : ELSE
375 : {
376 : /* hp filter 20Hz at 3dB for 48000KHz sampling rate
377 : [b,a] = butter(2, 20.0/24000.0, 'high');
378 : b =[ 0.998150511190452 -1.996301022380904 0.998150511190452]
379 : a =[1.000000000000000 -1.996297601769122 0.996304442992686]*/
380 2437503 : a1_fx = 2143508228 /* 1.996297601769122 Q30*/;
381 2437503 : a2_fx = -1069773750 /*-0.996304442992686 Q30*/;
382 2437503 : b1_fx = -2143511901 /*-1.996301022380904 Q30*/;
383 2437503 : b2_fx = 1071755951 /* 0.998150511190452 Q30*/;
384 : }
385 3304861 : move32();
386 3304861 : move32();
387 3304861 : move32();
388 3304861 : move32();
389 : Word64 W_sum, W_y0, W_y1, W_y2;
390 : Word32 x0, x1, x2;
391 :
392 3304861 : W_sum = W_mult0_32_32( b2_fx, mem_fx[2] ); /* b2*x2 */
393 3304861 : W_sum = W_add( W_sum, W_mult0_32_32( b1_fx, mem_fx[3] ) ); /* b1*x1 */
394 3304861 : x2 = L_shr( signal_fx[0], prescale );
395 3304861 : W_sum = W_add( W_sum, W_mult0_32_32( b2_fx, x2 ) ); /* b2*x0 */
396 3304861 : W_sum = W_add( W_sum, W_mult0_32_32( mem_fx[0], a2_fx ) ); /* y2*a2 */
397 3304861 : W_sum = W_add( W_sum, W_mult0_32_32( mem_fx[1], a1_fx ) ); /* y1*a1 */
398 3304861 : W_y2 = W_shl( W_sum, 1 + HP20_FX_COEFF_SCALE );
399 3304861 : signal_fx[0] = W_round64_L( W_shl( W_y2, prescale ) );
400 3304861 : move32();
401 :
402 3304861 : W_sum = W_mult0_32_32( b2_fx, mem_fx[3] ); /* b2*x2 */
403 3304861 : W_sum = W_add( W_sum, W_mult0_32_32( b1_fx, x2 ) ); /* b1*x1 */
404 3304861 : x1 = L_shr( signal_fx[1], prescale );
405 3304861 : W_sum = W_add( W_sum, W_mult0_32_32( b2_fx, x1 ) ); /* b2*x0 */
406 3304861 : W_sum = W_add( W_sum, W_mult0_32_32( mem_fx[1], a2_fx ) ); /* y2*a2 */
407 3304861 : W_sum = W_add( W_sum, W_mult0_32_32( W_round64_L( W_y2 ), a1_fx ) ); /* y1*a1 */
408 3304861 : W_y1 = W_shl( W_sum, 1 + HP20_FX_COEFF_SCALE );
409 3304861 : signal_fx[1] = W_round64_L( W_shl( W_y1, prescale ) );
410 3304861 : move32();
411 :
412 3304861 : diff = sub( prescale_current_frame, prescale );
413 3304861 : W_y1 = W_shr( W_y1, diff );
414 3304861 : W_y2 = W_shr( W_y2, diff );
415 3304861 : x2 = L_shr( x2, diff );
416 3304861 : x1 = L_shr( x1, diff );
417 :
418 2824552739 : FOR( i = 2; i < lg; i++ )
419 : {
420 2821247878 : W_sum = W_mult0_32_32( b2_fx, x2 ); /* b2*x2 */
421 2821247878 : W_sum = W_add( W_sum, W_mult0_32_32( b1_fx, x1 ) ); /* b1*x1 */
422 2821247878 : x0 = L_shr( signal_fx[i], prescale_current_frame );
423 2821247878 : W_sum = W_add( W_sum, W_mult0_32_32( b2_fx, x0 ) ); /* b2*x0 */
424 2821247878 : W_sum = W_add( W_sum, W_mult0_32_32( W_round64_L( W_y2 ), a2_fx ) ); /* y2*a2 */
425 2821247878 : W_sum = W_add( W_sum, W_mult0_32_32( W_round64_L( W_y1 ), a1_fx ) ); /* y1*a1 */
426 2821247878 : W_y0 = W_shl( W_sum, 1 + HP20_FX_COEFF_SCALE );
427 :
428 2821247878 : signal_fx[i] = W_round64_L( W_shl( W_y0, prescale_current_frame ) );
429 2821247878 : move32();
430 :
431 2821247878 : x2 = x1;
432 2821247878 : x1 = x0;
433 2821247878 : W_y2 = W_y1;
434 2821247878 : W_y1 = W_y0;
435 :
436 2821247878 : move32();
437 2821247878 : move32();
438 2821247878 : move64();
439 2821247878 : move64();
440 : }
441 :
442 3304861 : mem_fx[0] = W_round64_L( W_y2 );
443 3304861 : mem_fx[1] = W_round64_L( W_y1 );
444 3304861 : mem_fx[2] = x2;
445 3304861 : mem_fx[3] = x1;
446 :
447 3304861 : move32();
448 3304861 : move32();
449 3304861 : move32();
450 3304861 : move32();
451 :
452 3304861 : return;
453 : }
454 :
455 :
456 0 : void hp20_fx_32(
457 : Word32 signal_fx[],
458 : const Word16 lg,
459 : Word32 mem_fx[],
460 : const Word32 Fs )
461 : {
462 : Word16 i;
463 : Word32 a1_fx, a2_fx, b1_fx, b2_fx;
464 : Word16 Qx0, Qx1, Qx2, Qy1, Qprev_y1, Qy2, Qprev_y2, Qmin;
465 : Word64 x0_fx64, x1_fx64, x2_fx64, y0_fx64, y1_fx64, y2_fx64, R1, R2, R3, R4, R5;
466 :
467 0 : IF( EQ_32( Fs, 8000 ) )
468 : {
469 : /* hp filter 20Hz at 3dB for 8000KHz input sampling rate
470 : [b,a] = butter(2, 20.0/4000.0, 'high');
471 : b = [0.988954248067140 -1.977908496134280 0.988954248067140]
472 : a =[1.000000000000000 -1.977786483776764 0.978030508491796]*/
473 0 : a1_fx = 1061816033l /* 1.977786483776764 Q29*/;
474 0 : a2_fx = -525076131l /*-0.978030508491796 Q29*/;
475 0 : b1_fx = -1061881538l /*-1.977908496134280 Q29*/;
476 0 : b2_fx = 530940769l /* 0.988954248067140 Q29*/;
477 : }
478 0 : ELSE IF( EQ_32( Fs, 16000 ) )
479 : {
480 : /* hp filter 20Hz at 3dB for 16000KHz sampling rate
481 : [b,a] = butter(2, 20.0/8000.0, 'high');
482 : b =[ 0.994461788958195 -1.988923577916390 0.994461788958195]
483 : a =[1.000000000000000 -1.988892905899653 0.988954249933127] */
484 0 : a1_fx = 1067778748l /* 1.988892905899653 Q29*/;
485 0 : a2_fx = -530940770l /*-0.988954249933127 Q29*/;
486 0 : b1_fx = -1067795215l /*-1.988923577916390 Q29*/;
487 0 : b2_fx = 533897608l /* 0.994461788958195 Q29*/;
488 : }
489 0 : ELSE IF( EQ_32( Fs, 32000 ) )
490 : {
491 : /* hp filter 20Hz at 3dB for 32000KHz sampling rate
492 : [b,a] = butter(2, 20.0/16000.0, 'high');
493 : b =[0.997227049904470 -1.994454099808940 0.997227049904470]
494 : a =[1.000000000000000 -1.994446410541927 0.994461789075954]*/
495 0 : a1_fx = 1070760263l /* 1.994446410541927 Q29*/;
496 0 : a2_fx = -533897608l /*-0.994461789075954 Q29*/;
497 0 : b1_fx = -1070764392l /*-1.994454099808940 Q29*/;
498 0 : b2_fx = 535382196l /* 0.997227049904470 Q29*/;
499 : }
500 : ELSE
501 : {
502 : /* hp filter 20Hz at 3dB for 48000KHz sampling rate
503 : [b,a] = butter(2, 20.0/24000.0, 'high');
504 : b =[ 0.998150511190452 -1.996301022380904 0.998150511190452]
505 : a =[1.000000000000000 -1.996297601769122 0.996304442992686]*/
506 0 : a1_fx = 1071754114l /* 1.996297601769122 Q29*/;
507 0 : a2_fx = -534886875l /*-0.996304442992686 Q29*/;
508 0 : b1_fx = -1071755951l /*-1.996301022380904 Q29*/;
509 0 : b2_fx = 535877975l /* 0.998150511190452 Q29*/;
510 : }
511 0 : move32();
512 0 : move32();
513 0 : move32();
514 0 : move32();
515 :
516 0 : Qprev_y1 = extract_l( mem_fx[4] );
517 0 : Qprev_y2 = extract_l( mem_fx[5] );
518 0 : y1_fx64 = W_deposit32_l( mem_fx[0] );
519 0 : y2_fx64 = W_deposit32_l( mem_fx[1] );
520 0 : x0_fx64 = W_deposit32_l( mem_fx[2] );
521 0 : x1_fx64 = W_deposit32_l( mem_fx[3] );
522 :
523 0 : FOR( i = 0; i < lg; i++ )
524 : {
525 0 : x2_fx64 = x1_fx64;
526 0 : move64();
527 0 : x1_fx64 = x0_fx64;
528 0 : move64();
529 0 : x0_fx64 = W_deposit32_l( signal_fx[i] );
530 :
531 0 : Qy1 = W_norm( y1_fx64 );
532 0 : if ( y1_fx64 == 0 )
533 : {
534 0 : Qy1 = 62;
535 0 : move16();
536 : }
537 0 : Qy1 = sub( Qy1, 34 );
538 0 : R1 = W_mult0_32_32( W_shl_sat_l( y1_fx64, Qy1 ), a1_fx );
539 0 : Qy1 = add( Qy1, Qprev_y1 );
540 :
541 0 : Qy2 = W_norm( y2_fx64 );
542 0 : if ( y2_fx64 == 0 )
543 : {
544 0 : Qy2 = 62;
545 0 : move16();
546 : }
547 0 : Qy2 = sub( Qy2, 34 );
548 0 : R2 = W_mult0_32_32( W_shl_sat_l( y2_fx64, Qy2 ), a2_fx );
549 0 : Qy2 = add( Qy2, Qprev_y2 );
550 :
551 0 : Qx0 = W_norm( x0_fx64 );
552 0 : if ( x0_fx64 == 0 )
553 : {
554 0 : Qx0 = 62;
555 0 : move16();
556 : }
557 0 : Qx0 = sub( Qx0, 34 );
558 0 : R3 = W_mult0_32_32( W_shl_sat_l( x0_fx64, Qx0 ), b2_fx );
559 :
560 0 : Qx1 = W_norm( x1_fx64 );
561 0 : if ( x1_fx64 == 0 )
562 : {
563 0 : Qx1 = 62;
564 0 : move16();
565 : }
566 0 : Qx1 = sub( Qx1, 34 );
567 0 : R4 = W_mult0_32_32( W_shl_sat_l( x1_fx64, Qx1 ), b1_fx );
568 :
569 0 : Qx2 = W_norm( x2_fx64 );
570 0 : if ( x2_fx64 == 0 )
571 : {
572 0 : Qx2 = 62;
573 0 : move16();
574 : }
575 0 : Qx2 = sub( Qx2, 34 );
576 0 : R5 = W_mult0_32_32( W_shl_sat_l( x2_fx64, Qx2 ), b2_fx );
577 :
578 0 : Qmin = s_min( Qy1, Qy2 );
579 :
580 0 : y0_fx64 = W_add( W_shr( R1, sub( Qy1, Qmin ) ), W_shr( R2, sub( Qy2, Qmin ) ) );
581 :
582 0 : Qmin = s_min( Qmin, Qx0 );
583 0 : Qmin = s_min( Qmin, Qx1 );
584 0 : Qmin = s_min( Qmin, Qx2 );
585 :
586 0 : y0_fx64 = W_add( W_shr( y0_fx64, sub( s_min( Qy1, Qy2 ), Qmin ) ), W_add( W_shr( R3, sub( Qx0, Qmin ) ), W_add( W_shr( R4, sub( Qx1, Qmin ) ), W_shr( R5, sub( Qx2, Qmin ) ) ) ) );
587 :
588 0 : y0_fx64 = W_shr( y0_fx64, 29 );
589 :
590 0 : signal_fx[i] = W_extract_l( W_shr( y0_fx64, Qmin ) );
591 0 : move32();
592 0 : IF( signal_fx[i] < 0 )
593 : {
594 0 : signal_fx[i] = L_add( signal_fx[i], 1 );
595 0 : move32();
596 : }
597 :
598 0 : y2_fx64 = y1_fx64;
599 0 : y1_fx64 = y0_fx64;
600 0 : Qprev_y2 = Qprev_y1;
601 0 : Qprev_y1 = Qmin;
602 0 : move64();
603 0 : move64();
604 0 : move16();
605 0 : move16();
606 : }
607 :
608 0 : Qy1 = W_norm( y1_fx64 );
609 0 : test();
610 0 : IF( y1_fx64 != 0 && LT_16( Qy1, 32 ) )
611 : {
612 0 : y1_fx64 = W_shr( y1_fx64, sub( 32, Qy1 ) );
613 0 : Qprev_y1 = sub( Qprev_y1, sub( 32, Qy1 ) );
614 : }
615 :
616 0 : Qy2 = W_norm( y2_fx64 );
617 0 : test();
618 0 : IF( y2_fx64 != 0 && LT_16( Qy2, 32 ) )
619 : {
620 0 : y2_fx64 = W_shr( y2_fx64, sub( 32, Qy2 ) );
621 0 : Qprev_y2 = sub( Qprev_y2, sub( 32, Qy2 ) );
622 : }
623 :
624 0 : mem_fx[0] = W_extract_l( y1_fx64 );
625 0 : mem_fx[1] = W_extract_l( y2_fx64 );
626 0 : mem_fx[2] = W_extract_l( x0_fx64 );
627 0 : mem_fx[3] = W_extract_l( x1_fx64 );
628 0 : mem_fx[4] = Qprev_y1;
629 0 : mem_fx[5] = Qprev_y2;
630 :
631 0 : move32();
632 0 : move32();
633 0 : move32();
634 0 : move32();
635 0 : move32();
636 0 : move32();
637 :
638 0 : return;
639 : }
|