Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 :
6 : #include <stdint.h>
7 : #include <assert.h>
8 : #include "options.h"
9 : #include "cnst.h"
10 : #include "basop_util.h"
11 : #include "rom_com.h"
12 : #include "prot_fx.h"
13 :
14 : #define GET_ADJ2( T, L, F ) ( ( ( L ) << ( F ) ) - ( T ) )
15 212694 : void UnmapIndex(
16 : const Word16 PeriodicityIndex, /* Q0 */
17 : const Word16 Bandwidth, /* Q0 */
18 : const Word16 LtpPitchLag, /* Q0 */
19 : const Word16 SmallerLags, /* Q0 */
20 : Word16 *FractionalResolution, /* Q0 */
21 : Word32 *Lag /* Q0 */
22 : )
23 : {
24 : Word16 LtpPitchIndex, Multiplier;
25 : Word16 Lag16;
26 :
27 212694 : test();
28 212694 : IF( ( LtpPitchLag > 0 ) && ( s_and( PeriodicityIndex, kLtpHmFlag ) != 0 ) )
29 : {
30 55837 : LtpPitchIndex = shr( PeriodicityIndex, 9 ); /* Q0 */
31 55837 : Multiplier = s_and( PeriodicityIndex, 0xff ); /* Q0 */
32 :
33 55837 : assert( 0 <= LtpPitchIndex && LtpPitchIndex <= 16 );
34 55837 : assert( 1 <= Multiplier && Multiplier <= ( 1 << NumRatioBits[Bandwidth][LtpPitchIndex] ) );
35 :
36 55837 : *FractionalResolution = kLtpHmFractionalResolution; /* Q0 */
37 55837 : move16();
38 55837 : *Lag = L_shr( L_mult0( LtpPitchLag, Ratios_fx[Bandwidth][LtpPitchIndex][Multiplier - 1] ), 8 ); /* Q0 */
39 55837 : move32();
40 : }
41 : ELSE
42 : {
43 156857 : IF( LT_16( PeriodicityIndex, 16 ) )
44 : {
45 100692 : *FractionalResolution = 3; /* Q0 */
46 100692 : move16();
47 100692 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 0, 6, 3 ) ); /* Q0 */
48 : }
49 56165 : ELSE IF( LT_16( PeriodicityIndex, 80 ) )
50 : {
51 30443 : *FractionalResolution = 4; /* Q0 */
52 30443 : move16();
53 30443 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 16, 8, 4 ) ); /* Q0 */
54 : }
55 25722 : ELSE IF( LT_16( PeriodicityIndex, 208 ) )
56 : {
57 22099 : *FractionalResolution = 3; /* Q0 */
58 22099 : move16();
59 22099 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 80, 12, 3 ) ); /* Q0 */
60 : }
61 : ELSE
62 : {
63 3623 : test();
64 3623 : IF( LT_16( PeriodicityIndex, 224 ) || SmallerLags != 0 )
65 : {
66 2784 : *FractionalResolution = 1; /* Q0 */
67 2784 : move16();
68 2784 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 208, 28, 1 ) ); /* Q0 */
69 : }
70 : ELSE
71 : {
72 839 : *FractionalResolution = 0;
73 839 : move16();
74 839 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 224, 188, 0 ) ); /* Q0 */
75 : }
76 : }
77 156857 : *Lag = L_deposit_l( Lag16 ); /* Q0 */
78 156857 : move32();
79 : }
80 212694 : }
81 :
82 :
83 193818 : void ConfigureContextHm(
84 : const Word16 NumCoeffs, /* (I) Number of coefficients Q0*/
85 : const Word16 TargetBits, /* (I) Target bit budget (excl. Done flag) Q0*/
86 : const Word16 PeriodicityIndex, /* (I) Pitch related index Q0*/
87 : const Word16 LtpPitchLag, /* (I) TCX-LTP pitch in F.D. Q0*/
88 : CONTEXT_HM_CONFIG *hm_cfg /* (O) Context-based harmonic model configuration */
89 : )
90 : {
91 : Word8 Bandwidth, SmallerLags;
92 : Word32 i, Limit, Lag;
93 : Word16 j, Index, FractionalResolution;
94 : Word16 *tmp;
95 :
96 :
97 193818 : Bandwidth = 0;
98 193818 : move16();
99 193818 : if ( GE_16( NumCoeffs, 256 ) )
100 : {
101 193818 : Bandwidth = 1; /* Q0 */
102 193818 : move16();
103 : }
104 :
105 193818 : SmallerLags = 0;
106 193818 : move16();
107 193818 : test();
108 193818 : if ( ( LE_16( TargetBits, kSmallerLagsTargetBitsThreshold ) ) || ( Bandwidth == 0 ) )
109 : {
110 7555 : SmallerLags = 1; /* Q0 */
111 7555 : move16();
112 : }
113 :
114 193818 : UnmapIndex( PeriodicityIndex,
115 : Bandwidth,
116 : LtpPitchLag,
117 : SmallerLags,
118 : &FractionalResolution, &Lag );
119 :
120 : /* Set up and fill peakIndices */
121 193818 : hm_cfg->peakIndices = hm_cfg->indexBuffer; /* Q0 */
122 193818 : tmp = hm_cfg->peakIndices; /* Q0 */
123 193818 : Limit = L_shl( L_deposit_l( sub( NumCoeffs, 1 ) ), FractionalResolution ); /* Q0 */
124 193818 : IF( LT_32( Lag, Limit ) )
125 : {
126 20514832 : FOR( i = Lag; i < Limit; i += Lag )
127 : {
128 20321014 : Index = extract_l( L_shr( i, FractionalResolution ) ); /* Q0 */
129 20321014 : *tmp++ = sub( Index, 1 ); /* Q0 */
130 20321014 : move16();
131 20321014 : *tmp++ = Index; /* Q0 */
132 20321014 : move16();
133 20321014 : *tmp++ = add( Index, 1 ); /* Q0 */
134 20321014 : move16();
135 : }
136 : }
137 193818 : hm_cfg->numPeakIndices = (Word16) ( tmp - hm_cfg->indexBuffer ); /* Q0 */
138 193818 : move16();
139 :
140 : /* Set up and fill holeIndices */
141 193818 : hm_cfg->holeIndices = hm_cfg->indexBuffer + hm_cfg->numPeakIndices; /* Q0 */
142 193818 : tmp = hm_cfg->holeIndices; /* Q0 */
143 193818 : Index = 0;
144 193818 : move16();
145 193818 : IF( hm_cfg->numPeakIndices > 0 )
146 : {
147 20514832 : FOR( j = 0; j < hm_cfg->numPeakIndices; j += 3 )
148 : {
149 120405074 : FOR( ; Index < hm_cfg->peakIndices[j]; ++Index )
150 : {
151 100084060 : *tmp++ = Index; /* Q0 */
152 100084060 : move16();
153 : }
154 20321014 : Index = add( Index, 3 ); /* Skip the peak */
155 : }
156 : }
157 193818 : IF( LT_16( Index, NumCoeffs ) )
158 : {
159 1225630 : FOR( ; Index < NumCoeffs; ++Index )
160 : {
161 1045698 : *tmp++ = Index;
162 1045698 : move16();
163 : }
164 : }
165 193818 : hm_cfg->numHoleIndices = (Word16) ( tmp - hm_cfg->holeIndices );
166 193818 : move16();
167 193818 : *tmp++ = NumCoeffs;
168 193818 : move16(); /* Add extremal element signaling the end of the buffer */
169 193818 : }
170 :
171 193996 : Word16 CountIndexBits(
172 : Word16 Bandwidth, /* Q0 */
173 : Word16 PeriodicityIndex /* Q0 */
174 : )
175 : {
176 : Word16 result;
177 : Word16 PeriodicityIndexS;
178 :
179 193996 : result = 8;
180 193996 : move16();
181 193996 : PeriodicityIndexS = shr( PeriodicityIndex, 9 ); /* Q0 */
182 :
183 193996 : if ( s_and( PeriodicityIndex, kLtpHmFlag ) != 0 )
184 : {
185 47603 : result = NumRatioBits[Bandwidth][PeriodicityIndexS]; /* Q0 */
186 47603 : move16();
187 : }
188 :
189 193996 : return result;
190 : }
191 :
192 : #define WMC_TOOL_SKIP
193 :
194 18876 : Word32 tcx_hm_render(
195 : Word32 lag, /* i: pitch lag Q0 */
196 : Word16 fract_res, /* i: fractional resolution of the lag Q0 */
197 : Word16 p[] /* o: harmonic model Q13 */
198 : )
199 : {
200 : Word16 k, tmp, height;
201 : Word16 PeakDeviation;
202 : Word32 f0, tmp32;
203 :
204 : /* Set up overall shape */
205 18876 : f0 = L_shl( lag, sub( 15, fract_res ) ); /* Q31 */
206 :
207 18876 : tmp32 = Mpy_32_16_1( f0, -26474 );
208 18876 : tmp32 = L_shr_r( BASOP_Util_InvLog2( L_shl( tmp32, 7 ) ), 2 ); /* Q29 */
209 18876 : tmp32 = L_sub( 603979776L /* 1.125 in Q29 */, tmp32 ); /* Q29 */
210 18876 : tmp32 = L_add( L_add( tmp32, tmp32 ), Mpy_32_16_1( tmp32, 26214 ) ); /* Q29 */
211 18876 : height = round_fx( tmp32 ); /* Q13 */
212 :
213 18876 : tmp32 = Mpy_32_16_1( f0, -18910 );
214 18876 : tmp32 = L_shr_r( BASOP_Util_InvLog2( L_shl( tmp32, 7 ) ), 2 ); /* Q30 */
215 18876 : tmp32 = L_sub( 1395864371L /* 1.3 in Q30 */, tmp32 ); /* Q30 */
216 18876 : PeakDeviation = round_fx( tmp32 ); /* Q14 */
217 :
218 18876 : IF( GT_16( 13915, PeakDeviation ) )
219 : {
220 : /* A bit error was encountered */
221 0 : return 1;
222 : }
223 : ELSE
224 : {
225 18876 : tmp = div_s( 13915, PeakDeviation ); /* Q15 */
226 18876 : tmp = mult_r( tmp, tmp ); /* Q15 */
227 : }
228 :
229 18876 : tmp = div_s( 13915, PeakDeviation ); /* Q15 */
230 18876 : tmp = mult_r( tmp, tmp ); /* Q15 */
231 :
232 : /* Render the prototype peak */
233 18876 : p[kTcxHmParabolaHalfWidth] = height; /* Q13 */
234 18876 : move16();
235 :
236 94380 : FOR( k = 1; k <= kTcxHmParabolaHalfWidth; ++k )
237 : {
238 75504 : p[kTcxHmParabolaHalfWidth + k] = round_fx( Mpy_32_16_1( BASOP_Util_InvLog2( L_shl( L_mult0( i_mult2( negate( k ), k ), tmp ), 10 ) ), height ) ); /* Q13 */
239 75504 : move16();
240 : }
241 : /* Mirror */
242 94380 : FOR( k = -kTcxHmParabolaHalfWidth; k < 0; ++k )
243 : {
244 75504 : p[kTcxHmParabolaHalfWidth + k] = p[kTcxHmParabolaHalfWidth - k]; /* Q13 */
245 75504 : move16();
246 : }
247 :
248 18876 : return 0;
249 : }
250 :
251 :
252 43031 : void tcx_hm_modify_envelope(
253 : Word16 gain, /* i: HM gain Q11 */
254 : Word32 lag, /* i: pitch lag Q0 */
255 : Word16 fract_res, /* i: fractional resolution of the lag Q0 */
256 : Word16 p[], /* i: harmonic model Q13 */
257 : Word32 env[], /* i/o: envelope Q16 */
258 : Word16 L_frame /* i: number of spectral lines Q0 */
259 : )
260 : {
261 : Word16 k, h, x, l1, l2, L_frame_m1, L_frame_for_loop;
262 : Word16 inv_shape[2 * kTcxHmParabolaHalfWidth + 1];
263 :
264 43031 : IF( gain == 0 )
265 : {
266 11299 : return;
267 : }
268 :
269 317320 : FOR( k = 0; k < 2 * kTcxHmParabolaHalfWidth + 1; ++k )
270 : {
271 : /* Q24 = Q11 * Q13; 512 = 1.0 in Q24 format */
272 285588 : inv_shape[k] = div_s( 512, add( 512, mult_r( gain, p[k] ) ) ); /* Q15 */
273 285588 : move16();
274 : }
275 :
276 31732 : h = 1;
277 31732 : move16();
278 31732 : k = extract_l( L_shr( lag, fract_res ) ); /* Q0 */
279 :
280 31732 : L_frame_m1 = sub( L_frame, 1 ); /* Q0 */
281 31732 : L_frame_for_loop = add( L_frame, kTcxHmParabolaHalfWidth - 1 ); /* Q0 */
282 :
283 1614480 : WHILE( LE_16( k, L_frame_for_loop ) )
284 : {
285 1582748 : l1 = s_max( 0, sub( k, kTcxHmParabolaHalfWidth ) );
286 1582748 : l2 = s_min( add( k, kTcxHmParabolaHalfWidth ), L_frame_m1 );
287 15736623 : FOR( x = l1; x <= l2; ++x )
288 : {
289 14153875 : env[x] = Mpy_32_16_1( env[x], inv_shape[( x - k ) + kTcxHmParabolaHalfWidth] ); /* Q16 */
290 14153875 : move32();
291 : }
292 :
293 1582748 : h = add( h, 1 ); /* Q0 */
294 1582748 : k = extract_l( L_shr( imult3216( lag, h ), fract_res ) ); /* Q0 */
295 : }
296 : }
297 :
298 : #undef WMC_TOOL_SKIP
|