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