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 : #include <stdio.h>
33 :
34 : #include <stdint.h>
35 : #include "options.h"
36 : #include "prot_fx.h"
37 : #include "ivas_rom_com.h"
38 : #include <assert.h>
39 : #include "wmc_auto.h"
40 : #include <stdint.h>
41 : #include <math.h>
42 : #include "debug.h"
43 : #include "ivas_prot_fx.h"
44 :
45 : /*-----------------------------------------------------------------------------------------*
46 : * Local constants
47 : *-----------------------------------------------------------------------------------------*/
48 :
49 : #define IVAS_ONE_BY_960_Q37 143165577
50 : #define IVAS_ONE_BY_640_Q37 214748365
51 : #define IVAS_ONE_BY_320_Q37 429496730
52 : #define IVAS_ONE_BY_240_Q37 572662306
53 : #define IVAS_ONE_BY_160_Q37 858993459
54 : #define IVAS_ONE_BY_80_Q37 1717986918
55 : /*-----------------------------------------------------------------------------------------*
56 : * Function ivas_get_mdft_twid_factors()
57 : *
58 : * get twiddle tables for MDFT
59 : *-----------------------------------------------------------------------------------------*/
60 :
61 10278271 : static void ivas_get_mdft_twid_factors_fx(
62 : const Word16 length,
63 : const Word32 **ppTwid // Q31
64 : )
65 : {
66 10278271 : SWITCH( length )
67 : {
68 128223 : case L_FRAME48k:
69 128223 : *ppTwid = &ivas_mdft_coeff_cos_twid_960_fx[0]; // Q31
70 128223 : BREAK;
71 138723 : case L_FRAME32k:
72 138723 : *ppTwid = &ivas_mdft_coeff_cos_twid_640_fx[0]; // Q31
73 138723 : BREAK;
74 27240 : case L_FRAME16k:
75 27240 : *ppTwid = &ivas_mdft_coeff_cos_twid_320_fx[0]; // Q31
76 27240 : BREAK;
77 8008782 : case IVAS_240_PT_LEN:
78 8008782 : *ppTwid = &ivas_mdft_coeff_cos_twid_240_fx[0]; // Q31
79 8008782 : BREAK;
80 1233659 : case IVAS_160_PT_LEN:
81 1233659 : *ppTwid = &ivas_mdft_coeff_cos_twid_160_fx[0]; // Q31
82 1233659 : BREAK;
83 478022 : case IVAS_120_PT_LEN:
84 478022 : *ppTwid = &ivas_mdft_coeff_cos_twid_120_fx[0]; // Q31
85 478022 : BREAK;
86 263622 : case IVAS_80_PT_LEN:
87 263622 : *ppTwid = &ivas_mdft_coeff_cos_twid_80_fx[0]; // Q31
88 263622 : BREAK;
89 0 : case IVAS_40_PT_LEN:
90 0 : *ppTwid = &ivas_mdft_coeff_cos_twid_40_fx[0]; // Q31
91 0 : BREAK;
92 0 : default:
93 0 : assert( !"Not supported FFT length!" );
94 : BREAK;
95 : }
96 :
97 10278271 : return;
98 : }
99 : /*-----------------------------------------------------------------------------------------*
100 : * Function ivas_get_imdft_twid_factors()
101 : *
102 : * get twiddle tables for IMDFT
103 : *-----------------------------------------------------------------------------------------*/
104 :
105 1716481 : static void ivas_get_imdft_twid_factors_fx(
106 : const Word16 length,
107 : const Word32 **ppTwid // Q31
108 : )
109 : {
110 1716481 : SWITCH( length )
111 : {
112 307578 : case L_FRAME48k:
113 307578 : *ppTwid = ivas_mdft_coeff_cos_twid_960_fx; // Q31
114 307578 : BREAK;
115 206773 : case L_FRAME32k:
116 206773 : *ppTwid = ivas_mdft_coeff_cos_twid_640_fx; // Q31
117 206773 : BREAK;
118 39740 : case L_FRAME16k:
119 39740 : *ppTwid = ivas_mdft_coeff_cos_twid_320_fx; // Q31
120 39740 : BREAK;
121 1141652 : case 240:
122 1141652 : *ppTwid = ivas_mdft_coeff_cos_twid_240_fx; // Q31
123 1141652 : BREAK;
124 7378 : case 160:
125 7378 : *ppTwid = ivas_mdft_coeff_cos_twid_160_fx; // Q31
126 7378 : BREAK;
127 13360 : case 80:
128 13360 : *ppTwid = ivas_mdft_coeff_cos_twid_80_fx; // Q31
129 13360 : BREAK;
130 0 : default:
131 0 : assert( !"Not supported FFT length!" );
132 : }
133 :
134 1716481 : return;
135 : }
136 :
137 1716481 : static void get_one_by_length_fx(
138 : Word32 *one_by_length, // Q37
139 : const Word16 length )
140 : {
141 1716481 : IF( EQ_16( length, L_FRAME48k ) )
142 : {
143 307578 : *one_by_length = IVAS_ONE_BY_960_Q37; // Q37
144 307578 : move32();
145 : }
146 1408903 : ELSE IF( EQ_16( length, L_FRAME32k ) )
147 : {
148 206773 : *one_by_length = IVAS_ONE_BY_640_Q37; // Q37
149 206773 : move32();
150 : }
151 1202130 : ELSE IF( EQ_16( length, L_FRAME16k ) )
152 : {
153 39740 : *one_by_length = IVAS_ONE_BY_320_Q37; // Q37
154 39740 : move32();
155 : }
156 1162390 : ELSE IF( EQ_16( length, IVAS_240_PT_LEN ) )
157 : {
158 1141652 : *one_by_length = IVAS_ONE_BY_240_Q37; // Q37
159 1141652 : move32();
160 : }
161 20738 : ELSE IF( EQ_16( length, IVAS_160_PT_LEN ) )
162 : {
163 7378 : *one_by_length = IVAS_ONE_BY_160_Q37; // Q37
164 7378 : move32();
165 : }
166 13360 : ELSE IF( EQ_16( length, IVAS_80_PT_LEN ) )
167 : {
168 13360 : *one_by_length = IVAS_ONE_BY_80_Q37; // Q37
169 13360 : move32();
170 : }
171 : ELSE
172 : {
173 0 : assert( !"Not supported FFT length!" );
174 : }
175 :
176 1716481 : return;
177 : }
178 :
179 : /*-----------------------------------------------------------------------------------------*
180 : * Function ivas_ifft_cplx1()
181 : *
182 : * Complex IFFT implementation using fft()
183 : *-----------------------------------------------------------------------------------------*/
184 :
185 1716481 : static void ivas_ifft_cplx1_fx(
186 : Word32 *re, // inp: Qin -> out: Qin + 6
187 : Word32 *im, // inp: Qin -> out: Qin + 6
188 : const Word16 length )
189 : {
190 : Word16 i;
191 : Word32 one_by_length, tmp;
192 1716481 : get_one_by_length_fx( &one_by_length, length ); // Q37
193 :
194 : /* re-arrange inputs to use fft as ifft */
195 1716481 : re[0] = Mpy_32_32( re[0], one_by_length ); // ( Qin + Q37 ) - Q31 -> Qin + 6
196 1716481 : move32();
197 1716481 : im[0] = Mpy_32_32( im[0], one_by_length ); // ( Qin + Q37 ) - Q31 -> Qin + 6
198 1716481 : move32();
199 :
200 360002561 : FOR( i = 1; i <= length >> 1; i++ )
201 : {
202 358286080 : tmp = Mpy_32_32( re[length - i], one_by_length ); /*stl_arr_index Q: ( Qin + Q37 ) - Q31 -> Qin + 6 */
203 358286080 : re[length - i] = Mpy_32_32( re[i], one_by_length ); /*stl_arr_index Q: ( Qin + Q37 ) - Q31 -> Qin + 6 */
204 358286080 : move32();
205 358286080 : re[i] = tmp;
206 358286080 : move32();
207 :
208 358286080 : tmp = Mpy_32_32( im[length - i], one_by_length ); /*stl_arr_index Q: ( Qin + Q37 ) - Q31 -> Qin + 6 */
209 358286080 : im[length - i] = Mpy_32_32( im[i], one_by_length ); /*stl_arr_index Q: ( Qin + Q37 ) - Q31 -> Qin + 6 */
210 358286080 : move32();
211 358286080 : im[i] = tmp; // Q: ( Qin + Q37 ) - Q31 -> Qin + 6
212 358286080 : move32();
213 : }
214 :
215 1716481 : fft_fx( re, im, length, 1 );
216 :
217 1716481 : return;
218 : }
219 :
220 : /*-----------------------------------------------------------------------------------------*
221 : * Function ivas_mdft()
222 :
223 : * MDFT implementation
224 : *-----------------------------------------------------------------------------------------*/
225 :
226 10278271 : void ivas_mdft_fx(
227 : const Word32 *pIn, /* i : input time-domain signal Qin */
228 : Word32 *pOut_re, /* o : Real part of MDFT signal Qin */
229 : Word32 *pOut_im, /* o : Imag. part of MDFT signal Qin */
230 : const Word16 input_length, /* i : signal length */
231 : const Word16 mdft_length /* i : MDFT length */
232 : )
233 : {
234 : Word32 re[L_FRAME48k];
235 : Word32 im[L_FRAME48k];
236 : Word16 j, len_by_2;
237 : const Word32 *pTwid; // Q31
238 10278271 : len_by_2 = shr( mdft_length, 1 );
239 :
240 10278271 : ivas_get_mdft_twid_factors_fx( mdft_length, &pTwid );
241 10278271 : IF( EQ_16( mdft_length, input_length ) )
242 : {
243 1372245441 : FOR( j = 0; j < mdft_length; j++ )
244 : {
245 1366513920 : re[j] = Mpy_32_32( pIn[j], pTwid[j] ); // ( Qin + Q31 ) - Q31 -> Qin
246 1366513920 : move32();
247 1366513920 : im[j] = Mpy_32_32( L_negate( pIn[j] ), pTwid[mdft_length - j] ); // ( Qin + Q31 ) - Q31 -> Qin
248 1366513920 : move32();
249 : }
250 : }
251 : ELSE
252 : {
253 1056571950 : FOR( j = 0; j < mdft_length; j++ )
254 : {
255 1052025200 : re[j] = Msub_32_32( Mpy_32_32( pIn[j], pTwid[j] ), pIn[add( mdft_length, j )], pTwid[mdft_length - j] ); // ( Qin + Q31 ) - Q31 -> Qin
256 1052025200 : move32();
257 1052025200 : im[j] = Msub_32_32( Mpy_32_32( L_negate( pIn[j] ), pTwid[mdft_length - j] ), pIn[mdft_length + j], pTwid[j] ); // ( Qin + Q31 ) - Q31 -> Qin
258 1052025200 : move32();
259 : }
260 : }
261 :
262 10278271 : fft_fx( re, im, mdft_length, 1 );
263 1219547831 : FOR( j = 0; j < len_by_2; j++ )
264 : {
265 1209269560 : pOut_re[2 * j] = re[j]; // Qin
266 1209269560 : move32();
267 1209269560 : pOut_re[2 * j + 1] = re[mdft_length - j - 1]; // Qin
268 1209269560 : move32();
269 :
270 1209269560 : pOut_im[2 * j] = im[j]; // Qin
271 1209269560 : move32();
272 1209269560 : pOut_im[2 * j + 1] = L_negate( im[mdft_length - j - 1] ); // Qin
273 1209269560 : move32();
274 : }
275 10278271 : return;
276 : }
277 :
278 :
279 : /*-----------------------------------------------------------------------------------------*
280 : * Function ivas_imdft()
281 : *
282 : * iMDFT implementation
283 : * out buffer needs to have 2*length worth memory
284 : *-----------------------------------------------------------------------------------------*/
285 :
286 1716481 : void ivas_imdft_fx(
287 : const Word32 *pRe, /* i : Real part of MDFT signal Qin */
288 : const Word32 *pIm, /* i : Imag. part of MDFT signal Qin */
289 : Word32 *pOut, /* o : output time-domain signal Qin */
290 : const Word16 length /* i : signal length */
291 : )
292 : {
293 1716481 : Word32 *re_tmp = pOut;
294 1716481 : Word32 *im_tmp = pOut + length;
295 : Word32 tmp;
296 : Word16 j;
297 : Word16 len_by_2;
298 : const Word32 *pTwid; // Q31
299 1716481 : len_by_2 = shr( length, 1 );
300 :
301 1716481 : ivas_get_imdft_twid_factors_fx( length, &pTwid );
302 :
303 360002561 : FOR( j = 0; j < len_by_2; j++ )
304 : {
305 358286080 : re_tmp[j] = pRe[2 * j]; // Qin
306 358286080 : move32();
307 358286080 : re_tmp[j + len_by_2] = pRe[length - 2 * j - 1]; // Qin
308 358286080 : move32();
309 :
310 358286080 : im_tmp[j] = pIm[2 * j]; // Qin
311 358286080 : move32();
312 358286080 : im_tmp[j + len_by_2] = L_negate( pIm[length - 2 * j - 1] ); // Qin
313 358286080 : move32();
314 : }
315 :
316 1716481 : ivas_ifft_cplx1_fx( re_tmp, im_tmp, length );
317 : // re_tmp: Qin + 6
318 : // im_tmp: Qin + 6
319 :
320 718288641 : FOR( j = 0; j < length; j++ )
321 : {
322 716572160 : tmp = Msub_32_32( Mpy_32_32( L_shr( re_tmp[j], Q6 ), pTwid[j] ), L_shr( im_tmp[j], Q6 ), pTwid[length - j] ); // ( ( Qin + Q6 - Q6 ) + Q31 ) - Q31 -> Qin
323 716572160 : im_tmp[j] = L_negate( Madd_32_32( Mpy_32_32( L_shr( re_tmp[j], Q6 ), pTwid[length - j] ), L_shr( im_tmp[j], Q6 ), pTwid[j] ) ); // ( ( Qin + Q6 - Q6 ) + Q31 ) - Q31 -> Qin
324 716572160 : move32();
325 716572160 : re_tmp[j] = tmp; // ( ( Qin + Q6 - Q6 ) + Q31 ) - Q31 -> Qin
326 716572160 : move32();
327 : }
328 1716481 : return;
329 : }
|