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