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 212169 : 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 212169 : test();
28 212169 : IF( ( LtpPitchLag > 0 ) && ( s_and( PeriodicityIndex, kLtpHmFlag ) != 0 ) )
29 : {
30 55533 : LtpPitchIndex = shr( PeriodicityIndex, 9 ); /* Q0 */
31 55533 : Multiplier = s_and( PeriodicityIndex, 0xff ); /* Q0 */
32 :
33 55533 : assert( 0 <= LtpPitchIndex && LtpPitchIndex <= 16 );
34 55533 : assert( 1 <= Multiplier && Multiplier <= ( 1 << NumRatioBits[Bandwidth][LtpPitchIndex] ) );
35 :
36 55533 : *FractionalResolution = kLtpHmFractionalResolution; /* Q0 */
37 55533 : move16();
38 55533 : *Lag = L_shr( L_mult0( LtpPitchLag, Ratios_fx[Bandwidth][LtpPitchIndex][Multiplier - 1] ), 8 ); /* Q0 */
39 55533 : move32();
40 : }
41 : ELSE
42 : {
43 156636 : IF( LT_16( PeriodicityIndex, 16 ) )
44 : {
45 100561 : *FractionalResolution = 3; /* Q0 */
46 100561 : move16();
47 100561 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 0, 6, 3 ) ); /* Q0 */
48 : }
49 56075 : ELSE IF( LT_16( PeriodicityIndex, 80 ) )
50 : {
51 30394 : *FractionalResolution = 4; /* Q0 */
52 30394 : move16();
53 30394 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 16, 8, 4 ) ); /* Q0 */
54 : }
55 25681 : ELSE IF( LT_16( PeriodicityIndex, 208 ) )
56 : {
57 22060 : *FractionalResolution = 3; /* Q0 */
58 22060 : move16();
59 22060 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 80, 12, 3 ) ); /* Q0 */
60 : }
61 : ELSE
62 : {
63 3621 : test();
64 3621 : IF( LT_16( PeriodicityIndex, 224 ) || SmallerLags != 0 )
65 : {
66 2788 : *FractionalResolution = 1; /* Q0 */
67 2788 : move16();
68 2788 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 208, 28, 1 ) ); /* Q0 */
69 : }
70 : ELSE
71 : {
72 833 : *FractionalResolution = 0;
73 833 : move16();
74 833 : Lag16 = add( PeriodicityIndex, GET_ADJ2( 224, 188, 0 ) ); /* Q0 */
75 : }
76 : }
77 156636 : *Lag = L_deposit_l( Lag16 ); /* Q0 */
78 156636 : move32();
79 : }
80 212169 : }
81 :
82 :
83 193230 : 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 193230 : Bandwidth = 0;
98 193230 : move16();
99 193230 : if ( GE_16( NumCoeffs, 256 ) )
100 : {
101 193230 : Bandwidth = 1; /* Q0 */
102 193230 : move16();
103 : }
104 :
105 193230 : SmallerLags = 0;
106 193230 : move16();
107 193230 : test();
108 193230 : if ( ( LE_16( TargetBits, kSmallerLagsTargetBitsThreshold ) ) || ( Bandwidth == 0 ) )
109 : {
110 7567 : SmallerLags = 1; /* Q0 */
111 7567 : move16();
112 : }
113 :
114 193230 : UnmapIndex( PeriodicityIndex,
115 : Bandwidth,
116 : LtpPitchLag,
117 : SmallerLags,
118 : &FractionalResolution, &Lag );
119 :
120 : /* Set up and fill peakIndices */
121 193230 : hm_cfg->peakIndices = hm_cfg->indexBuffer; /* Q0 */
122 193230 : tmp = hm_cfg->peakIndices; /* Q0 */
123 193230 : Limit = L_shl( L_deposit_l( sub( NumCoeffs, 1 ) ), FractionalResolution ); /* Q0 */
124 193230 : IF( LT_32( Lag, Limit ) )
125 : {
126 20493348 : FOR( i = Lag; i < Limit; i += Lag )
127 : {
128 20300118 : Index = extract_l( L_shr( i, FractionalResolution ) ); /* Q0 */
129 20300118 : *tmp++ = sub( Index, 1 ); /* Q0 */
130 20300118 : move16();
131 20300118 : *tmp++ = Index; /* Q0 */
132 20300118 : move16();
133 20300118 : *tmp++ = add( Index, 1 ); /* Q0 */
134 20300118 : move16();
135 : }
136 : }
137 193230 : hm_cfg->numPeakIndices = (Word16) ( tmp - hm_cfg->indexBuffer ); /* Q0 */
138 193230 : move16();
139 :
140 : /* Set up and fill holeIndices */
141 193230 : hm_cfg->holeIndices = hm_cfg->indexBuffer + hm_cfg->numPeakIndices; /* Q0 */
142 193230 : tmp = hm_cfg->holeIndices; /* Q0 */
143 193230 : Index = 0;
144 193230 : move16();
145 193230 : IF( hm_cfg->numPeakIndices > 0 )
146 : {
147 20493348 : FOR( j = 0; j < hm_cfg->numPeakIndices; j += 3 )
148 : {
149 120315782 : FOR( ; Index < hm_cfg->peakIndices[j]; ++Index )
150 : {
151 100015664 : *tmp++ = Index; /* Q0 */
152 100015664 : move16();
153 : }
154 20300118 : Index = add( Index, 3 ); /* Skip the peak */
155 : }
156 : }
157 193230 : IF( LT_16( Index, NumCoeffs ) )
158 : {
159 1223170 : FOR( ; Index < NumCoeffs; ++Index )
160 : {
161 1043662 : *tmp++ = Index;
162 1043662 : move16();
163 : }
164 : }
165 193230 : hm_cfg->numHoleIndices = (Word16) ( tmp - hm_cfg->holeIndices );
166 193230 : move16();
167 193230 : *tmp++ = NumCoeffs;
168 193230 : move16(); /* Add extremal element signaling the end of the buffer */
169 193230 : }
170 :
171 193465 : Word16 CountIndexBits(
172 : Word16 Bandwidth, /* Q0 */
173 : Word16 PeriodicityIndex /* Q0 */
174 : )
175 : {
176 : Word16 result;
177 : Word16 PeriodicityIndexS;
178 :
179 193465 : result = 8;
180 193465 : move16();
181 193465 : PeriodicityIndexS = shr( PeriodicityIndex, 9 ); /* Q0 */
182 :
183 193465 : if ( s_and( PeriodicityIndex, kLtpHmFlag ) != 0 )
184 : {
185 47335 : result = NumRatioBits[Bandwidth][PeriodicityIndexS]; /* Q0 */
186 47335 : move16();
187 : }
188 :
189 193465 : return result;
190 : }
191 :
192 : #define WMC_TOOL_SKIP
193 :
194 18939 : 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 18939 : f0 = L_shl( lag, sub( 15, fract_res ) ); /* Q31 */
206 :
207 18939 : tmp32 = Mpy_32_16_1( f0, -26474 );
208 18939 : tmp32 = L_shr_r( BASOP_Util_InvLog2( L_shl( tmp32, 7 ) ), 2 ); /* Q29 */
209 18939 : tmp32 = L_sub( 603979776L /* 1.125 in Q29 */, tmp32 ); /* Q29 */
210 18939 : tmp32 = L_add( L_add( tmp32, tmp32 ), Mpy_32_16_1( tmp32, 26214 ) ); /* Q29 */
211 18939 : height = round_fx( tmp32 ); /* Q13 */
212 :
213 18939 : tmp32 = Mpy_32_16_1( f0, -18910 );
214 18939 : tmp32 = L_shr_r( BASOP_Util_InvLog2( L_shl( tmp32, 7 ) ), 2 ); /* Q30 */
215 18939 : tmp32 = L_sub( 1395864371L /* 1.3 in Q30 */, tmp32 ); /* Q30 */
216 18939 : PeakDeviation = round_fx( tmp32 ); /* Q14 */
217 :
218 18939 : IF( GT_16( 13915, PeakDeviation ) )
219 : {
220 : /* A bit error was encountered */
221 0 : return 1;
222 : }
223 : ELSE
224 : {
225 18939 : tmp = div_s( 13915, PeakDeviation ); /* Q15 */
226 18939 : tmp = mult_r( tmp, tmp ); /* Q15 */
227 : }
228 :
229 18939 : tmp = div_s( 13915, PeakDeviation ); /* Q15 */
230 18939 : tmp = mult_r( tmp, tmp ); /* Q15 */
231 :
232 : /* Render the prototype peak */
233 18939 : p[kTcxHmParabolaHalfWidth] = height; /* Q13 */
234 18939 : move16();
235 :
236 94695 : FOR( k = 1; k <= kTcxHmParabolaHalfWidth; ++k )
237 : {
238 75756 : 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 75756 : move16();
240 : }
241 : /* Mirror */
242 94695 : FOR( k = -kTcxHmParabolaHalfWidth; k < 0; ++k )
243 : {
244 75756 : p[kTcxHmParabolaHalfWidth + k] = p[kTcxHmParabolaHalfWidth - k]; /* Q13 */
245 75756 : move16();
246 : }
247 :
248 18939 : return 0;
249 : }
250 :
251 :
252 43176 : 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 43176 : IF( gain == 0 )
265 : {
266 11325 : return;
267 : }
268 :
269 318510 : FOR( k = 0; k < 2 * kTcxHmParabolaHalfWidth + 1; ++k )
270 : {
271 : /* Q24 = Q11 * Q13; 512 = 1.0 in Q24 format */
272 286659 : inv_shape[k] = div_s( 512, add( 512, mult_r( gain, p[k] ) ) ); /* Q15 */
273 286659 : move16();
274 : }
275 :
276 31851 : h = 1;
277 31851 : move16();
278 31851 : k = extract_l( L_shr( lag, fract_res ) ); /* Q0 */
279 :
280 31851 : L_frame_m1 = sub( L_frame, 1 ); /* Q0 */
281 31851 : L_frame_for_loop = add( L_frame, kTcxHmParabolaHalfWidth - 1 ); /* Q0 */
282 :
283 1623112 : WHILE( LE_16( k, L_frame_for_loop ) )
284 : {
285 1591261 : l1 = s_max( 0, sub( k, kTcxHmParabolaHalfWidth ) );
286 1591261 : l2 = s_min( add( k, kTcxHmParabolaHalfWidth ), L_frame_m1 );
287 15820906 : FOR( x = l1; x <= l2; ++x )
288 : {
289 14229645 : env[x] = Mpy_32_16_1( env[x], inv_shape[( x - k ) + kTcxHmParabolaHalfWidth] ); /* Q16 */
290 14229645 : move32();
291 : }
292 :
293 1591261 : h = add( h, 1 ); /* Q0 */
294 1591261 : k = extract_l( L_shr( imult3216( lag, h ), fract_res ) ); /* Q0 */
295 : }
296 : }
297 :
298 : #undef WMC_TOOL_SKIP
|