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 <assert.h>
38 : #include <stdint.h>
39 : #include "options.h"
40 : #include "basop_proto_func.h"
41 : #include "basop_util.h"
42 :
43 : #define WMC_TOOL_SKIP
44 :
45 : #define NC_MAX 8
46 :
47 : static Word16 E_LPC_f_lsp_pol_get( const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1 );
48 :
49 :
50 : /*
51 : * E_LPC_f_lsp_a_conversion
52 : *
53 : * Parameters:
54 : * lsp I: Line spectral pairs Q15
55 : * a O: Predictor coefficients (order = m) Qx (The Q factor of the output to be deduced from a(0))
56 : * m I: order of LP filter
57 : *
58 : * Function:
59 : * Convert ISPs to predictor coefficients a[]
60 : *
61 : * Returns:
62 : * void
63 : */
64 31484 : void basop_E_LPC_f_lsp_a_conversion(
65 : const Word16 *lsp, /* Q15 */
66 : Word16 *a, /* Qx */
67 : const Word16 m /* Q0 */
68 : )
69 : {
70 : Word16 i, j, k;
71 : Word32 f1[NC_MAX + 1], f2[NC_MAX + 1];
72 : Word16 nc;
73 : Word32 t0;
74 : Word16 Ovf, Ovf2;
75 :
76 :
77 : /*-----------------------------------------------------*
78 : * Find the polynomials F1(z) and F2(z) *
79 : *-----------------------------------------------------*/
80 :
81 31484 : nc = shr( m, 1 );
82 :
83 31484 : assert( m == 16 || m == 10 );
84 :
85 31484 : Ovf = 0;
86 31484 : move16();
87 31484 : Ovf = E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, Ovf, 1 ); /* Q0 */
88 31484 : Ovf2 = E_LPC_f_lsp_pol_get( &lsp[1], f2, nc, Ovf, 1 ); /* Q0 */
89 31484 : IF( sub( Ovf2, Ovf ) != 0 )
90 : {
91 : /* to ensure similar scaling for f1 and f2 in case
92 : an overflow would be detected only in f2,
93 : but this case never happen on my dtb */
94 0 : E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, s_max( Ovf2, Ovf ), 1 );
95 : }
96 : /*-----------------------------------------------------*
97 : * Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) *
98 : *-----------------------------------------------------*/
99 : /*modification*/
100 31484 : k = sub( nc, 1 );
101 283356 : FOR( i = 0; i <= k; i++ )
102 : {
103 251872 : f1[nc - i] = L_add( f1[nc - i], f1[nc - i - 1] ); /* Q23 */
104 251872 : move32();
105 251872 : f2[nc - i] = L_sub( f2[nc - i], f2[nc - i - 1] ); /* Q23 */
106 251872 : move32();
107 : }
108 :
109 : /*-----------------------------------------------------*
110 : * A(z) = (F1(z)+F2(z))/2 *
111 : * F1(z) is symmetric and F2(z) is antisymmetric *
112 : *-----------------------------------------------------*/
113 :
114 31484 : t0 = L_deposit_l( 0 );
115 283356 : FOR( i = 1; i <= nc; i++ )
116 : {
117 251872 : t0 = L_max( t0, L_abs( L_add( f1[i], f2[i] ) ) ); /* Q23 */
118 251872 : t0 = L_max( t0, L_abs( L_sub( f1[i], f2[i] ) ) ); /* Q23 */
119 : }
120 31484 : k = s_min( norm_l( t0 ), 6 );
121 31484 : a[0] = shl( 256, k );
122 31484 : move16();
123 31484 : test();
124 31484 : IF( Ovf || Ovf2 )
125 : {
126 0 : a[0] = shl( 256, sub( k, Ovf ) );
127 0 : move16();
128 : }
129 31484 : j = m;
130 283356 : FOR( i = 1; i <= nc; i++ )
131 : {
132 : /* a[i] = 0.5*(f1[i] + f2[i]) */
133 251872 : t0 = L_add( f1[i], f2[i] ); /* Q23 */
134 251872 : t0 = L_shl( t0, k );
135 251872 : a[i] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */
136 :
137 : /* a[j] = 0.5*(f1[i] - f2[i]) */
138 251872 : t0 = L_sub( f1[i], f2[i] ); /* Q23 */
139 251872 : t0 = L_shl( t0, k );
140 251872 : a[j] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */
141 251872 : j--;
142 : }
143 :
144 31484 : return;
145 : }
146 :
147 :
148 : /*---------------------------------------------------------------------------
149 : * procedure reorder_lsf()
150 : *
151 : * To make sure that the lsfs are properly ordered and to keep a certain
152 : * minimum distance between consecutive lsfs.
153 : *--------------------------------------------------------------------------*/
154 0 : void basop_reorder_lsf(
155 : Word16 *lsf, /* i/o: LSFs in the frequency domain (0..0.5) Q(x2.56)*/
156 : const Word16 min_dist, /* i : minimum required distance x2.56*/
157 : const Word16 n, /* i : LPC order Q0*/
158 : const Word32 Fs /* i : sampling frequency Q0*/
159 : )
160 : {
161 : Word16 i, lsf_min, n_m_1;
162 : Word16 lsf_max;
163 :
164 0 : lsf_min = min_dist; /* Q2.56 */
165 0 : move16();
166 :
167 : /*-----------------------------------------------------------------------*
168 : * Verify the LSF ordering and minimum GAP
169 : *-----------------------------------------------------------------------*/
170 :
171 0 : FOR( i = 0; i < n; i++ )
172 : {
173 0 : if ( sub( lsf[i], lsf_min ) < 0 )
174 : {
175 0 : lsf[i] = lsf_min; /* Q2.56 */
176 0 : move16();
177 : }
178 0 : lsf_min = add( lsf[i], min_dist ); /* Q2.56 */
179 : }
180 :
181 : /*-----------------------------------------------------------------------*
182 : * Reverify the LSF ordering and minimum GAP in the reverse order (security)
183 : *-----------------------------------------------------------------------*/
184 :
185 0 : lsf_max = round_fx( L_sub( L_shr( L_mult0( extract_l( L_shr( Fs, 1 ) ), 1311 ), 9 - 16 ), L_deposit_h( min_dist ) ) ); /* Q0 + Q9 , 1311 is 2.56 in Q9 */
186 :
187 0 : n_m_1 = sub( n, 1 ); /* Q0 */
188 0 : IF( sub( lsf[n_m_1], lsf_max ) > 0 ) /* If danger of unstable filter in case of resonance in HF */
189 : {
190 0 : FOR( i = n_m_1; i >= 0; i-- ) /* Reverify the minimum LSF gap in the reverse direction */
191 : {
192 0 : if ( sub( lsf[i], lsf_max ) > 0 )
193 : {
194 0 : lsf[i] = lsf_max; /* Q2.56 */
195 0 : move16();
196 : }
197 0 : lsf_max = sub( lsf[i], min_dist ); /* Q2.56 */
198 : }
199 : }
200 :
201 0 : return;
202 : }
203 :
204 :
205 : /*
206 : * E_LPC_f_lsp_pol_get
207 : *
208 : * Parameters:
209 : * lsp/isp I: Line spectral pairs (cosine domaine) Q15
210 : * f O: the coefficients of F1 or F2 Q23
211 : * n I: no of coefficients (m/2)
212 : * == NC for F1(z); == NC-1 for F2(z)
213 : * fact I: scaling factor
214 : *
215 : *-----------------------------------------------------------*
216 : * procedure E_LPC_f_lsp_pol_get: *
217 : * ~~~~~~~~~~~ *
218 : * Find the polynomial F1(z) or F2(z) from the LSPs. *
219 : * This is performed by expanding the product polynomials: *
220 : * *
221 : * F1(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 ) *
222 : * i=0,2,4,6,8 *
223 : * F2(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 ) *
224 : * i=1,3,5,7,9 *
225 : * *
226 : * where LSP_i are the LSPs in the cosine domain. *
227 : * *
228 : *-----------------------------------------------------------*
229 : * R.A.Salami October 1990 *
230 : *-----------------------------------------------------------*
231 : */
232 62968 : static Word16 E_LPC_f_lsp_pol_get(
233 : const Word16 lsp[], /* Q15 */
234 : Word32 f[], /* Q23 */
235 : const Word16 n, /* Q0 */
236 : const Word16 past_Ovf, /* Q0 */
237 : const Word16 isMODE1 /* Q0 */
238 : )
239 : {
240 : /* All computation in Q23 */
241 : const Word16 *plsp;
242 : Word16 i, j;
243 : Word16 b;
244 : Word32 b32;
245 62968 : Word16 Ovf = 0;
246 : Word16 Q_out;
247 : Word16 m2;
248 : Flag Overflow;
249 62968 : move16(); // move for Ovf = 0
250 :
251 62968 : Q_out = 31 - 23;
252 62968 : move16();
253 62968 : Ovf = past_Ovf;
254 62968 : move16();
255 :
256 62968 : test();
257 62968 : if ( past_Ovf && isMODE1 ) /* Currently this feature is implemented only in MODE1 */
258 : {
259 : /* In some NB cases, overflow where detectected
260 : in f1 or f2 polynomial computation when it
261 : happen we reduce the precision of the computing
262 : to limit the risk of saturation*/
263 0 : Q_out = add( Q_out, past_Ovf );
264 : }
265 62968 : Overflow = 0;
266 62968 : move16();
267 62968 : plsp = lsp;
268 62968 : f[0] = L_shl( 1, sub( 31, Q_out ) );
269 62968 : move32();
270 : /*b = -2.0f * *plsp;*/
271 62968 : b = *plsp;
272 62968 : move16();
273 62968 : m2 = shl( -2, sub( 15, Q_out ) );
274 62968 : f[1] = L_mult( b, m2 ); /* Q23 */
275 62968 : move32();
276 :
277 503744 : FOR( i = 2; i <= n; i++ )
278 : {
279 440776 : plsp += 2;
280 : /*b = 2.0f * *plsp;*/
281 440776 : move16();
282 440776 : b = *plsp;
283 440776 : b32 = L_mult( b, m2 );
284 :
285 : /*f[i] = -b*f[i-1] + 2.0f*f[i-2];*/
286 440776 : move32();
287 440776 : f[i] = L_shl( L_sub( f[i - 2], Mpy_32_16_1( f[i - 1], b ) ), 1 ); /* Q23 */
288 :
289 1763104 : FOR( j = i - 1; j > 1; j-- )
290 : {
291 : /*f[j] += b*f[j-1] + f[j-2];*/
292 1322328 : move32();
293 1322328 : f[j] = L_add( f[j], L_sub( f[j - 2], L_shl( Mpy_32_16_1( f[j - 1], b ), 1 ) ) ); /* Q23 */
294 : }
295 440776 : move32();
296 440776 : f[1] = L_add( f[1], b32 ); /* Q23 */
297 : }
298 :
299 :
300 62968 : test();
301 62968 : IF( Overflow > 0 && isMODE1 )
302 : {
303 0 : assert( 0 );
304 : /* If an overflow is detected, redo the computation with 1 bit less */
305 : Ovf = add( Ovf, 1 );
306 : Ovf = E_LPC_f_lsp_pol_get( lsp, f, n, Ovf, isMODE1 ); /* Q0 */
307 : }
308 62968 : return Ovf;
309 : }
310 :
311 : #undef WMC_TOOL_SKIP
|