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.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 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 : /*
45 : * hp20
46 : *
47 : * Function:
48 : * 2nd order high pass filter with nominal cut off frequency at 20 Hz.
49 : *
50 : * Returns:
51 : * void
52 : */
53 :
54 7910700 : static Word32 HP50_Mode2_Mpy_32_16_fix( Word32 a, Word16 b )
55 : {
56 7910700 : Word32 result = Mpy_32_16_1( a, b );
57 : /* perform rounding towards lower value for negative results */
58 7910700 : if ( result < 0 )
59 3913929 : result = L_add( result, 1 );
60 7910700 : return result;
61 : }
62 :
63 5289300 : static Word32 HP50_Mpy_32_32_fix( Word32 a, Word32 b )
64 : {
65 5289300 : Word32 result = Mpy_32_32( a, b );
66 : /* perform rounding towards lower value for negative results */
67 5289300 : if ( result < 0 )
68 2644199 : result = L_add( result, 1 );
69 5289300 : return result;
70 : }
71 :
72 :
73 3100 : static void filter_2nd_order(
74 : Word16 signal[],
75 : const Word16 stride,
76 : const Word16 prescale,
77 : const Word16 lg,
78 : Word32 mem[4],
79 : Word32 a1,
80 : Word32 a2,
81 : Word32 b1,
82 : Word32 b2 )
83 : {
84 :
85 : Word16 i;
86 : Word16 x2, x1;
87 : Word32 L_sum, L_y1, L_y2;
88 : #ifndef ISSUE_1836_replace_overflow_libcom
89 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
90 : Flag Overflow = 0;
91 : #endif
92 : #endif
93 :
94 :
95 : /*
96 : * Saturation: The states of the filter, namely L_y1 and L_y2 shall
97 : * never saturate, because that causes error in the filter feedback.
98 : * The final output written into signal[] might saturate because of
99 : * unavoidable filter overshoot.
100 : */
101 :
102 : /* Execute first 2 iterations with 32-bit x anx y memory values */
103 : BASOP_SATURATE_ERROR_ON_EVS
104 3100 : L_sum = HP50_Mpy_32_32_fix( b2, mem[2] ); /* b2*x2 */
105 3100 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( b1, mem[3] ) ); /* b1*x1 */
106 3100 : x2 = shr( signal[0], prescale );
107 3100 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x2 ) ); /* b2*x0 */
108 3100 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( mem[0], a2 ) ); /* y2*a2 */
109 3100 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( mem[1], a1 ) ); /* y1*a1 */
110 :
111 : #ifdef ISSUE_1836_replace_overflow_libcom
112 3100 : L_y2 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
113 : BASOP_SATURATE_ERROR_OFF_EVS
114 : BASOP_SATURATE_WARNING_OFF_EVS
115 3100 : signal[0] = round_fx_sat( L_shl_sat( L_y2, prescale ) );
116 : #else
117 : L_y2 = L_shl_o( L_sum, HP20_COEFF_SCALE, &Overflow );
118 : BASOP_SATURATE_ERROR_OFF_EVS
119 : BASOP_SATURATE_WARNING_OFF_EVS
120 : signal[0] = round_fx_o( L_shl_o( L_y2, prescale, &Overflow ), &Overflow );
121 : #endif
122 :
123 : BASOP_SATURATE_WARNING_ON_EVS
124 :
125 : BASOP_SATURATE_ERROR_ON_EVS
126 3100 : L_sum = HP50_Mpy_32_32_fix( b2, mem[3] ); /* b2*x2 */
127 3100 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b1, x2 ) ); /* b1*x1 */
128 3100 : x1 = shr( signal[stride], prescale );
129 3100 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x1 ) ); /* b2*x0 */
130 3100 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( mem[1], a2 ) ); /* y2*a2 */
131 3100 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y2, a1 ) ); /* y1*a1 */
132 :
133 : #ifdef ISSUE_1836_replace_overflow_libcom
134 3100 : L_y1 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
135 : BASOP_SATURATE_ERROR_OFF_EVS
136 : BASOP_SATURATE_WARNING_OFF_EVS
137 3100 : signal[stride] = round_fx_sat( L_shl_sat( L_y1, prescale ) );
138 : #else
139 : L_y1 = L_shl_o( L_sum, HP20_COEFF_SCALE, &Overflow );
140 : BASOP_SATURATE_ERROR_OFF_EVS
141 : BASOP_SATURATE_WARNING_OFF_EVS
142 : signal[stride] = round_fx_o( L_shl_o( L_y1, prescale, &Overflow ), &Overflow );
143 : #endif
144 : BASOP_SATURATE_WARNING_ON_EVS
145 3100 : move16();
146 :
147 : /* New we use a trick and toggle x1/x2 and L_y1/L_y2 to save a few cycles unrolling the loop by 2 */
148 1320000 : FOR( i = 2; i < lg; i += 2 )
149 : {
150 : /* y[i+0] = b2*x[i-2] + b1*x[i-1] + b2*x[i-0] + a2*y[i-2] + a1*y[i-1]; */
151 : BASOP_SATURATE_ERROR_ON_EVS
152 1316900 : L_sum = HP50_Mode2_Mpy_32_16_fix( b2, x2 );
153 1316900 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b1, x1 ) );
154 1316900 : x2 = shr( signal[i * stride], prescale );
155 1316900 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x2 ) );
156 1316900 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y2, a2 ) );
157 1316900 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y1, a1 ) );
158 :
159 : #ifdef ISSUE_1836_replace_overflow_libcom
160 1316900 : L_y2 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
161 : BASOP_SATURATE_ERROR_OFF_EVS
162 : BASOP_SATURATE_WARNING_OFF_EVS
163 1316900 : signal[i_mult( i, stride )] = round_fx_sat( L_shl_sat( L_y2, prescale ) );
164 : #else
165 : L_y2 = L_shl_o( L_sum, HP20_COEFF_SCALE, &Overflow );
166 : BASOP_SATURATE_ERROR_OFF_EVS
167 : BASOP_SATURATE_WARNING_OFF_EVS
168 : signal[i_mult( i, stride )] = round_fx_o( L_shl_o( L_y2, prescale, &Overflow ), &Overflow );
169 : #endif
170 : BASOP_SATURATE_WARNING_ON_EVS
171 : /* y[i+1] = b2*x[i-1] + b1*x[i-0] + b2*x[i+1] + a2*y[i-1] + a1*y[i+0]; */
172 : BASOP_SATURATE_ERROR_ON_EVS
173 1316900 : L_sum = HP50_Mode2_Mpy_32_16_fix( b2, x1 );
174 1316900 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b1, x2 ) );
175 1316900 : x1 = shr( signal[( i + 1 ) * stride], prescale );
176 1316900 : L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x1 ) );
177 1316900 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y1, a2 ) );
178 1316900 : L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y2, a1 ) );
179 :
180 : #ifdef ISSUE_1836_replace_overflow_libcom
181 1316900 : L_y1 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
182 : BASOP_SATURATE_ERROR_OFF_EVS
183 : BASOP_SATURATE_WARNING_OFF_EVS
184 1316900 : signal[i_mult( add( i, 1 ), stride )] = round_fx_sat( L_shl_sat( L_y1, prescale ) );
185 : #else
186 : L_y1 = L_shl_o( L_sum, HP20_COEFF_SCALE, &Overflow );
187 : BASOP_SATURATE_ERROR_OFF_EVS
188 : BASOP_SATURATE_WARNING_OFF_EVS
189 : signal[i_mult( add( i, 1 ), stride )] = round_fx_o( L_shl_o( L_y1, prescale, &Overflow ), &Overflow );
190 : #endif
191 : BASOP_SATURATE_WARNING_ON_EVS
192 1316900 : move16();
193 : }
194 : /* update static filter memory from variables */
195 3100 : mem[0] = L_y2;
196 3100 : move32();
197 3100 : mem[1] = L_y1;
198 3100 : move32();
199 3100 : mem[2] = L_deposit_h( x2 );
200 3100 : move32();
201 3100 : mem[3] = L_deposit_h( x1 );
202 3100 : move32();
203 :
204 :
205 3100 : return;
206 : }
207 :
208 :
209 3100 : void hp20( Word16 signal[], /* i/o: signal to filter any */
210 : const Word16 stride, /* i : stride to be applied accessing signal */
211 : const Word16 lg, /* i : length of signal (integer) Q0 */
212 : Word32 mem[5], /* i/o: static filter memory with this layout: */
213 : /* mem[0]: y[-2] (32-bit) */
214 : /* mem[1]; y[-1] (32-bit) */
215 : /* mem[2]: x[-2] << 16 */
216 : /* mem[3]: x[-1] << 16 */
217 : /* Note: mem[0..3] need to be scaled per frame */
218 : /* mem[4]: states scale */
219 : const Word32 sFreq ) /* i : input sampling rate Q0 */
220 : {
221 : Word32 a1, b1, a2, b2;
222 : Word16 prescale, prescaleOld, diff;
223 : #ifndef ISSUE_1836_replace_overflow_libcom
224 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
225 : Flag Overflow = 0;
226 : #endif
227 : #endif
228 :
229 :
230 3100 : prescale = getScaleFactor16( signal, lg );
231 3100 : prescaleOld = extract_l( mem[4] );
232 3100 : diff = norm_l( L_shl_sat( mem[2], prescaleOld ) );
233 3100 : if ( mem[2] != 0 )
234 : {
235 3090 : prescale = s_min( prescale, diff );
236 : }
237 : #ifdef ISSUE_1836_replace_overflow_libcom
238 3100 : diff = norm_l( L_shl_sat( mem[3], prescaleOld ) );
239 : #else
240 : diff = norm_l( L_shl_o( mem[3], prescaleOld, &Overflow ) );
241 : #endif
242 3100 : if ( mem[3] != 0 )
243 : {
244 3084 : prescale = s_min( prescale, diff );
245 : }
246 : /* Take into account the left shift performed into the loop + 1 bit headroom*/
247 3100 : prescale = s_max( -12, sub( 1 + HP20_COEFF_SCALE, prescale ) );
248 3100 : IF( prescale != prescaleOld )
249 : {
250 1265 : diff = sub( prescale, prescaleOld );
251 : #ifdef ISSUE_1836_replace_overflow_libcom
252 1265 : mem[0] = L_shr_sat( mem[0], diff );
253 1265 : move32();
254 1265 : mem[1] = L_shr_sat( mem[1], diff );
255 1265 : move32();
256 1265 : mem[2] = L_shr_sat( mem[2], diff );
257 1265 : move32();
258 1265 : mem[3] = L_shr_sat( mem[3], diff ); //?sat
259 : #else
260 : mem[0] = L_shr_o( mem[0], diff, &Overflow );
261 : move32();
262 : mem[1] = L_shr_o( mem[1], diff, &Overflow );
263 : move32();
264 : mem[2] = L_shr_o( mem[2], diff, &Overflow );
265 : move32();
266 : mem[3] = L_shr_o( mem[3], diff, &Overflow );
267 : #endif
268 1265 : move32();
269 1265 : mem[4] = L_deposit_l( prescale );
270 : }
271 :
272 3100 : IF( EQ_32( sFreq, 8000 ) )
273 : {
274 : /* hp filter 20Hz at 3dB for 8000 Hz input sampling rate
275 : [b,a] = butter(2, 20.0/4000.0, 'high');
276 : b = [0.988954248067140 -1.977908496134280 0.988954248067140]
277 : a = [1.000000000000000 -1.977786483776764 0.978030508491796]*/
278 0 : a1 = 1061816033l /* 1.977786483776764 Q29*/;
279 0 : move32();
280 0 : a2 = -525076131l /*-0.978030508491796 Q29*/;
281 0 : move32();
282 0 : b1 = -1061881538l /*-1.977908496134280 Q29*/;
283 0 : move32();
284 0 : b2 = 530940769l /* 0.988954248067140 Q29*/;
285 0 : move32();
286 : }
287 3100 : ELSE IF( EQ_32( sFreq, 16000 ) )
288 : {
289 : /* hp filter 20Hz at 3dB for 16000KHz sampling rate
290 : [b,a] = butter(2, 20.0/8000.0, 'high');
291 : b = [0.994461788958195 -1.988923577916390 0.994461788958195]
292 : a = [1.000000000000000 -1.988892905899653 0.988954249933127] */
293 0 : a1 = 1067778748l /* 1.988892905899653 Q29*/;
294 0 : move32();
295 0 : a2 = -530940770l /*-0.988954249933127 Q29*/;
296 0 : move32();
297 0 : b1 = -1067795215l /*-1.988923577916390 Q29*/;
298 0 : move32();
299 0 : b2 = 533897608l /* 0.994461788958195 Q29*/;
300 0 : move32();
301 : }
302 3100 : ELSE IF( EQ_32( sFreq, 32000 ) )
303 : {
304 : /* hp filter 20Hz at 3dB for 32000KHz sampling rate
305 : [b,a] = butter(2, 20.0/16000.0, 'high');
306 : b = [0.997227049904470 -1.994454099808940 0.997227049904470]
307 : a = [1.000000000000000 -1.994446410541927 0.994461789075954]*/
308 1050 : a1 = 1070760263l /* 1.994446410541927 Q29*/;
309 1050 : move32();
310 1050 : a2 = -533897608l /*-0.994461789075954 Q29*/;
311 1050 : move32();
312 1050 : b1 = -1070764392l /*-1.994454099808940 Q29*/;
313 1050 : move32();
314 1050 : b2 = 535382196l /* 0.997227049904470 Q29*/;
315 1050 : move32();
316 : }
317 : ELSE
318 : {
319 2050 : assert( sFreq == 48000 );
320 : /* hp filter 20Hz at 3dB for 48000KHz sampling rate
321 : [b,a] = butter(2, 20.0/24000.0, 'high');
322 : b =[0.998150511190452 -1.996301022380904 0.998150511190452]
323 : a =[1.000000000000000 -1.996297601769122 0.996304442992686]*/
324 2050 : a1 = 1071754114l /* 1.996297601769122 Q29*/;
325 2050 : move32();
326 2050 : a2 = -534886875l /*-0.996304442992686 Q29*/;
327 2050 : move32();
328 2050 : b1 = -1071755951l /*-1.996301022380904 Q29*/;
329 2050 : move32();
330 2050 : b2 = 535877975l /* 0.998150511190452 Q29*/;
331 2050 : move32();
332 : }
333 :
334 :
335 3100 : filter_2nd_order( signal, stride, prescale, lg,
336 : mem, a1, a2, b1, b2 );
337 :
338 3100 : return;
339 : }
340 :
341 :
342 : #ifdef HP20_FIX32_RECODING
343 : void hp20_fx_32(
344 : Word32 signal_fx[],
345 : const Word16 lg,
346 : Word32 mem_fx[],
347 : const Word32 Fs )
348 : {
349 : Word32 i;
350 : Word32 a1_fx, a2_fx, b1_fx, b2_fx;
351 : Word32 diff_pos, diff_neg;
352 : #ifndef ISSUE_1836_replace_overflow_libcom
353 : Flag Overflow = 0;
354 : #endif
355 : Word16 prescale, prescaleOld, prescale_current_frame, diff;
356 :
357 : prescale = getScaleFactor32( signal_fx, lg );
358 : prescale_current_frame = s_min( 3, sub( 1 + HP20_COEFF_SCALE, prescale ) );
359 :
360 :
361 : prescaleOld = extract_l( mem_fx[4] );
362 :
363 : #ifdef ISSUE_1836_replace_overflow_libcom
364 : diff_pos = norm_l( L_shl_sat( L_max( mem_fx[2], mem_fx[3] ), prescaleOld ) );
365 : diff_neg = norm_l( L_shl_sat( L_min( mem_fx[2], mem_fx[3] ), prescaleOld ) );
366 : #else
367 : diff_pos = norm_l( L_shl_o( L_max( mem_fx[2], mem_fx[3] ), prescaleOld, &Overflow ) );
368 : diff_neg = norm_l( L_shl_o( L_min( mem_fx[2], mem_fx[3] ), prescaleOld, &Overflow ) );
369 : #endif
370 :
371 :
372 : diff = L_max( diff_pos, diff_neg );
373 :
374 : IF( NE_16( diff, 0 ) )
375 : {
376 : prescale = s_min( prescale, diff );
377 : }
378 :
379 : prescale = s_min( 3, sub( 1 + HP20_COEFF_SCALE, prescale ) );
380 :
381 : diff = sub( prescale, prescaleOld );
382 : #ifdef ISSUE_1836_replace_overflow_libcom
383 : mem_fx[0] = L_shr_sat( mem_fx[0], diff );
384 : move32();
385 : mem_fx[1] = L_shr_sat( mem_fx[1], diff );
386 : move32();
387 : mem_fx[2] = L_shr_sat( mem_fx[2], diff );
388 : move32();
389 : mem_fx[3] = L_shr_sat( mem_fx[3], diff );
390 : #else
391 : mem_fx[0] = L_shr_o( mem_fx[0], diff, &Overflow );
392 : move32();
393 : mem_fx[1] = L_shr_o( mem_fx[1], diff, &Overflow );
394 : move32();
395 : mem_fx[2] = L_shr_o( mem_fx[2], diff, &Overflow );
396 : move32();
397 : mem_fx[3] = L_shr_o( mem_fx[3], diff, &Overflow );
398 : #endif
399 : move32();
400 : mem_fx[4] = L_deposit_l( prescale_current_frame );
401 : move32();
402 :
403 : IF( EQ_32( Fs, 8000 ) )
404 : {
405 : /* hp filter 20Hz at 3dB for 8000KHz input sampling rate
406 : [b,a] = butter(2, 20.0/4000.0, 'high');
407 : b = [0.988954248067140 -1.977908496134280 0.988954248067140]
408 : a =[1.000000000000000 -1.977786483776764 0.978030508491796]*/
409 : a1_fx = 1061816033l /* 1.977786483776764 Q29*/;
410 : a2_fx = -525076131l /*-0.978030508491796 Q29*/;
411 : b1_fx = -1061881538l /*-1.977908496134280 Q29*/;
412 : b2_fx = 530940769l /* 0.988954248067140 Q29*/;
413 : }
414 : ELSE IF( EQ_32( Fs, 16000 ) )
415 : {
416 : /* hp filter 20Hz at 3dB for 16000KHz sampling rate
417 : [b,a] = butter(2, 20.0/8000.0, 'high');
418 : b =[ 0.994461788958195 -1.988923577916390 0.994461788958195]
419 : a =[1.000000000000000 -1.988892905899653 0.988954249933127] */
420 : a1_fx = 1067778748l /* 1.988892905899653 Q29*/;
421 : a2_fx = -530940770l /*-0.988954249933127 Q29*/;
422 : b1_fx = -1067795215l /*-1.988923577916390 Q29*/;
423 : b2_fx = 533897608l /* 0.994461788958195 Q29*/;
424 : }
425 : ELSE IF( EQ_32( Fs, 32000 ) )
426 : {
427 : /* hp filter 20Hz at 3dB for 32000KHz sampling rate
428 : [b,a] = butter(2, 20.0/16000.0, 'high');
429 : b =[0.997227049904470 -1.994454099808940 0.997227049904470]
430 : a =[1.000000000000000 -1.994446410541927 0.994461789075954]*/
431 : a1_fx = 1070760263l /* 1.994446410541927 Q29*/;
432 : a2_fx = -533897608l /*-0.994461789075954 Q29*/;
433 : b1_fx = -1070764392l /*-1.994454099808940 Q29*/;
434 : b2_fx = 535382196l /* 0.997227049904470 Q29*/;
435 : }
436 : ELSE
437 : {
438 : /* hp filter 20Hz at 3dB for 48000KHz sampling rate
439 : [b,a] = butter(2, 20.0/24000.0, 'high');
440 : b =[ 0.998150511190452 -1.996301022380904 0.998150511190452]
441 : a =[1.000000000000000 -1.996297601769122 0.996304442992686]*/
442 : a1_fx = 1071754114l /* 1.996297601769122 Q29*/;
443 : a2_fx = -534886875l /*-0.996304442992686 Q29*/;
444 : b1_fx = -1071755951l /*-1.996301022380904 Q29*/;
445 : b2_fx = 535877975l /* 0.998150511190452 Q29*/;
446 : }
447 : move32();
448 : move32();
449 : move32();
450 : move32();
451 : Word64 W_sum, W_y0, W_y1, W_y2;
452 : Word32 x0, x1, x2;
453 :
454 : W_sum = W_mult_32_32( b2_fx, mem_fx[2] ); /* b2*x2 */
455 : W_sum = W_mac_32_32( W_sum, b1_fx, mem_fx[3] ); /* b1*x1 */
456 : x2 = L_shr( signal_fx[0], prescale );
457 : W_sum = W_mac_32_32( W_sum, b2_fx, x2 ); /* b2*x0 */
458 : W_sum = W_mac_32_32( W_sum, mem_fx[0], a2_fx ); /* y2*a2 */
459 : W_sum = W_mac_32_32( W_sum, mem_fx[1], a1_fx ); /* y1*a1 */
460 : W_y2 = W_shl( W_sum, HP20_COEFF_SCALE );
461 : signal_fx[0] = W_extract_h( W_shl( W_y2, prescale ) );
462 : move32();
463 :
464 : W_sum = W_mult_32_32( b2_fx, mem_fx[3] ); /* b2*x2 */
465 : W_sum = W_mac_32_32( W_sum, b1_fx, x2 ); /* b1*x1 */
466 : x1 = L_shr( signal_fx[1], prescale );
467 : W_sum = W_mac_32_32( W_sum, b2_fx, x1 ); /* b2*x0 */
468 : W_sum = W_mac_32_32( W_sum, mem_fx[1], a2_fx ); /* y2*a2 */
469 : W_sum = W_mac_32_32( W_sum, W_extract_h( W_y2 ), a1_fx ); /* y1*a1 */
470 : W_y1 = W_shl( W_sum, HP20_COEFF_SCALE );
471 : signal_fx[1] = W_extract_h( W_shl( W_y1, prescale ) );
472 : move32();
473 :
474 : diff = sub( prescale_current_frame, prescale );
475 : W_y1 = W_shr( W_y1, diff );
476 : W_y2 = W_shr( W_y2, diff );
477 : x2 = L_shr( x2, diff );
478 : x1 = L_shr( x1, diff );
479 :
480 : FOR( i = 2; i < lg; i++ )
481 : {
482 : W_sum = W_mult_32_32( b2_fx, x2 ); /* b2*x2 */
483 : W_sum = W_mac_32_32( W_sum, b1_fx, x1 ); /* b1*x1 */
484 : x0 = L_shr( signal_fx[i], prescale_current_frame );
485 : W_sum = W_mac_32_32( W_sum, b2_fx, x0 ); /* b2*x0 */
486 : W_sum = W_mac_32_32( W_sum, W_extract_h( W_y2 ), a2_fx ); /* y2*a2 */
487 : W_sum = W_mac_32_32( W_sum, W_extract_h( W_y1 ), a1_fx ); /* y1*a1 */
488 : W_y0 = W_shl( W_sum, HP20_COEFF_SCALE );
489 :
490 : signal_fx[i] = W_extract_h( W_shl( W_y0, prescale_current_frame ) );
491 : move32();
492 :
493 : x2 = x1;
494 : x1 = x0;
495 : W_y2 = W_y1;
496 : W_y1 = W_y0;
497 :
498 : move32();
499 : move32();
500 : move64();
501 : move64();
502 : }
503 :
504 : mem_fx[0] = W_extract_h( W_y2 );
505 : mem_fx[1] = W_extract_h( W_y1 );
506 : mem_fx[2] = x2;
507 : mem_fx[3] = x1;
508 :
509 : move32();
510 : move32();
511 : move32();
512 : move32();
513 :
514 : return;
515 : }
516 : #else
517 1047767 : void hp20_fx_32(
518 : Word32 signal_fx[],
519 : const Word16 lg,
520 : Word32 mem_fx[],
521 : const Word32 Fs )
522 : {
523 : Word16 i;
524 : Word32 a1_fx, a2_fx, b1_fx, b2_fx;
525 : Word16 Qx0, Qx1, Qx2, Qy1, Qprev_y1, Qy2, Qprev_y2, Qmin;
526 : Word64 x0_fx64, x1_fx64, x2_fx64, y0_fx64, y1_fx64, y2_fx64, R1, R2, R3, R4, R5;
527 :
528 1047767 : IF( EQ_32( Fs, 8000 ) )
529 : {
530 : /* hp filter 20Hz at 3dB for 8000KHz input sampling rate
531 : [b,a] = butter(2, 20.0/4000.0, 'high');
532 : b = [0.988954248067140 -1.977908496134280 0.988954248067140]
533 : a =[1.000000000000000 -1.977786483776764 0.978030508491796]*/
534 0 : a1_fx = 1061816033l /* 1.977786483776764 Q29*/;
535 0 : a2_fx = -525076131l /*-0.978030508491796 Q29*/;
536 0 : b1_fx = -1061881538l /*-1.977908496134280 Q29*/;
537 0 : b2_fx = 530940769l /* 0.988954248067140 Q29*/;
538 : }
539 1047767 : ELSE IF( EQ_32( Fs, 16000 ) )
540 : {
541 : /* hp filter 20Hz at 3dB for 16000KHz sampling rate
542 : [b,a] = butter(2, 20.0/8000.0, 'high');
543 : b =[ 0.994461788958195 -1.988923577916390 0.994461788958195]
544 : a =[1.000000000000000 -1.988892905899653 0.988954249933127] */
545 101123 : a1_fx = 1067778748l /* 1.988892905899653 Q29*/;
546 101123 : a2_fx = -530940770l /*-0.988954249933127 Q29*/;
547 101123 : b1_fx = -1067795215l /*-1.988923577916390 Q29*/;
548 101123 : b2_fx = 533897608l /* 0.994461788958195 Q29*/;
549 : }
550 946644 : ELSE IF( EQ_32( Fs, 32000 ) )
551 : {
552 : /* hp filter 20Hz at 3dB for 32000KHz sampling rate
553 : [b,a] = butter(2, 20.0/16000.0, 'high');
554 : b =[0.997227049904470 -1.994454099808940 0.997227049904470]
555 : a =[1.000000000000000 -1.994446410541927 0.994461789075954]*/
556 238621 : a1_fx = 1070760263l /* 1.994446410541927 Q29*/;
557 238621 : a2_fx = -533897608l /*-0.994461789075954 Q29*/;
558 238621 : b1_fx = -1070764392l /*-1.994454099808940 Q29*/;
559 238621 : b2_fx = 535382196l /* 0.997227049904470 Q29*/;
560 : }
561 : ELSE
562 : {
563 : /* hp filter 20Hz at 3dB for 48000KHz sampling rate
564 : [b,a] = butter(2, 20.0/24000.0, 'high');
565 : b =[ 0.998150511190452 -1.996301022380904 0.998150511190452]
566 : a =[1.000000000000000 -1.996297601769122 0.996304442992686]*/
567 708023 : a1_fx = 1071754114l /* 1.996297601769122 Q29*/;
568 708023 : a2_fx = -534886875l /*-0.996304442992686 Q29*/;
569 708023 : b1_fx = -1071755951l /*-1.996301022380904 Q29*/;
570 708023 : b2_fx = 535877975l /* 0.998150511190452 Q29*/;
571 : }
572 1047767 : move32();
573 1047767 : move32();
574 1047767 : move32();
575 1047767 : move32();
576 :
577 1047767 : Qprev_y1 = extract_l( mem_fx[4] );
578 1047767 : Qprev_y2 = extract_l( mem_fx[5] );
579 1047767 : y1_fx64 = W_deposit32_l( mem_fx[0] );
580 1047767 : y2_fx64 = W_deposit32_l( mem_fx[1] );
581 1047767 : x0_fx64 = W_deposit32_l( mem_fx[2] );
582 1047767 : x1_fx64 = W_deposit32_l( mem_fx[3] );
583 :
584 865826647 : FOR( i = 0; i < lg; i++ )
585 : {
586 864778880 : x2_fx64 = x1_fx64;
587 864778880 : move64();
588 864778880 : x1_fx64 = x0_fx64;
589 864778880 : move64();
590 864778880 : x0_fx64 = W_deposit32_l( signal_fx[i] );
591 :
592 864778880 : Qy1 = W_norm( y1_fx64 );
593 864778880 : if ( y1_fx64 == 0 )
594 : {
595 5910301 : Qy1 = 62;
596 5910301 : move16();
597 : }
598 864778880 : Qy1 = sub( Qy1, 34 );
599 864778880 : R1 = W_mult0_32_32( W_shl_sat_l( y1_fx64, Qy1 ), a1_fx );
600 864778880 : Qy1 = add( Qy1, Qprev_y1 );
601 :
602 864778880 : Qy2 = W_norm( y2_fx64 );
603 864778880 : if ( y2_fx64 == 0 )
604 : {
605 5916097 : Qy2 = 62;
606 5916097 : move16();
607 : }
608 864778880 : Qy2 = sub( Qy2, 34 );
609 864778880 : R2 = W_mult0_32_32( W_shl_sat_l( y2_fx64, Qy2 ), a2_fx );
610 864778880 : Qy2 = add( Qy2, Qprev_y2 );
611 :
612 864778880 : Qx0 = W_norm( x0_fx64 );
613 864778880 : if ( x0_fx64 == 0 )
614 : {
615 27460745 : Qx0 = 62;
616 27460745 : move16();
617 : }
618 864778880 : Qx0 = sub( Qx0, 34 );
619 864778880 : R3 = W_mult0_32_32( W_shl_sat_l( x0_fx64, Qx0 ), b2_fx );
620 :
621 864778880 : Qx1 = W_norm( x1_fx64 );
622 864778880 : if ( x1_fx64 == 0 )
623 : {
624 27466083 : Qx1 = 62;
625 27466083 : move16();
626 : }
627 864778880 : Qx1 = sub( Qx1, 34 );
628 864778880 : R4 = W_mult0_32_32( W_shl_sat_l( x1_fx64, Qx1 ), b1_fx );
629 :
630 864778880 : Qx2 = W_norm( x2_fx64 );
631 864778880 : if ( x2_fx64 == 0 )
632 : {
633 27471414 : Qx2 = 62;
634 27471414 : move16();
635 : }
636 864778880 : Qx2 = sub( Qx2, 34 );
637 864778880 : R5 = W_mult0_32_32( W_shl_sat_l( x2_fx64, Qx2 ), b2_fx );
638 :
639 864778880 : Qmin = s_min( Qy1, Qy2 );
640 :
641 864778880 : y0_fx64 = W_add( W_shr( R1, sub( Qy1, Qmin ) ), W_shr( R2, sub( Qy2, Qmin ) ) );
642 :
643 864778880 : Qmin = s_min( Qmin, Qx0 );
644 864778880 : Qmin = s_min( Qmin, Qx1 );
645 864778880 : Qmin = s_min( Qmin, Qx2 );
646 :
647 864778880 : 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 ) ) ) ) );
648 :
649 864778880 : y0_fx64 = W_shr( y0_fx64, 29 );
650 :
651 864778880 : signal_fx[i] = W_extract_l( W_shr( y0_fx64, Qmin ) );
652 864778880 : move32();
653 864778880 : IF( signal_fx[i] < 0 )
654 : {
655 430018645 : signal_fx[i] = L_add( signal_fx[i], 1 );
656 430018645 : move32();
657 : }
658 :
659 864778880 : y2_fx64 = y1_fx64;
660 864778880 : y1_fx64 = y0_fx64;
661 864778880 : Qprev_y2 = Qprev_y1;
662 864778880 : Qprev_y1 = Qmin;
663 864778880 : move64();
664 864778880 : move64();
665 864778880 : move16();
666 864778880 : move16();
667 : }
668 :
669 1047767 : Qy1 = W_norm( y1_fx64 );
670 1047767 : test();
671 1047767 : IF( y1_fx64 != 0 && LT_16( Qy1, 32 ) )
672 : {
673 0 : y1_fx64 = W_shr( y1_fx64, sub( 32, Qy1 ) );
674 0 : Qprev_y1 = sub( Qprev_y1, sub( 32, Qy1 ) );
675 : }
676 :
677 1047767 : Qy2 = W_norm( y2_fx64 );
678 1047767 : test();
679 1047767 : IF( y2_fx64 != 0 && LT_16( Qy2, 32 ) )
680 : {
681 0 : y2_fx64 = W_shr( y2_fx64, sub( 32, Qy2 ) );
682 0 : Qprev_y2 = sub( Qprev_y2, sub( 32, Qy2 ) );
683 : }
684 :
685 1047767 : mem_fx[0] = W_extract_l( y1_fx64 );
686 1047767 : mem_fx[1] = W_extract_l( y2_fx64 );
687 1047767 : mem_fx[2] = W_extract_l( x0_fx64 );
688 1047767 : mem_fx[3] = W_extract_l( x1_fx64 );
689 1047767 : mem_fx[4] = Qprev_y1;
690 1047767 : mem_fx[5] = Qprev_y2;
691 :
692 1047767 : move32();
693 1047767 : move32();
694 1047767 : move32();
695 1047767 : move32();
696 1047767 : move32();
697 1047767 : move32();
698 :
699 1047767 : return;
700 : }
701 : #endif
|