Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include "options.h" /* Compilation switches */
6 : #include "cnst.h" /* Common constants */
7 : #include "prot_fx.h" /* Function prototypes */
8 : #include "stl.h"
9 :
10 : /*-------------------------------------------------------------------*
11 : * Local function prototypes
12 : *-------------------------------------------------------------------*/
13 :
14 : static void nearest_neighbor_2D8_fx( const Word32 x[], Word16 y[] );
15 : static Word32 compute_error_2D8_fx( const Word32 x[], const Word16 y[] );
16 :
17 : /*--------------------------------------------------------------*
18 : * RE8_PPV:
19 : *
20 : * NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE RE8
21 : * the algorithm is based on the definition of RE8 as
22 : * RE8 = (2D8) U (2D8+[1,1,1,1,1,1,1,1])
23 : * it applies the coset decoding of Sloane and Conway
24 : * --------------------------------------------------------------*/
25 :
26 2411654 : void re8_PPV_fx(
27 : const Word32 x[], /* i : point in R^8 Q15 */
28 : Word16 y[] /* o : point in RE8 (8-dimensional integer vector) Q0*/
29 : )
30 : {
31 : Word16 i, y0[8];
32 : Word32 e0, e1, x1[8];
33 :
34 : /*--------------------------------------------------------------*
35 : * find the nearest neighbor y0 of x in 2D8
36 : *--------------------------------------------------------------*/
37 2411654 : nearest_neighbor_2D8_fx( x, y0 );
38 :
39 : /*--------------------------------------------------------------*
40 : * find the nearest neighbor y1 of x in 2D8+(1,...,1) (by coset decoding)
41 : *--------------------------------------------------------------*/
42 :
43 21704886 : FOR( i = 0; i < 8; i++ )
44 : {
45 19293232 : x1[i] = L_sub( x[i], QR ); /* Q15 */
46 19293232 : move32();
47 : }
48 2411654 : nearest_neighbor_2D8_fx( x1, y );
49 :
50 21704886 : FOR( i = 0; i < 8; i++ )
51 : {
52 19293232 : y[i] = add( y[i], 1 ); /* Q0 */
53 19293232 : move16();
54 : }
55 :
56 : /*--------------------------------------------------------------*
57 : * compute e0=||x-y0||^2 and e1=||x-y1||^2
58 : *--------------------------------------------------------------*/
59 :
60 2411654 : e0 = compute_error_2D8_fx( x, y0 );
61 2411654 : e1 = compute_error_2D8_fx( x, y );
62 :
63 :
64 : /*--------------------------------------------------------------*
65 : * select best candidate y0 or y1 to minimize distortion
66 : *--------------------------------------------------------------*/
67 2411654 : IF( LT_32( e0, e1 ) )
68 : {
69 1371268 : Copy( y0, y, 8 ); /* Q0 */
70 : }
71 :
72 2411654 : return;
73 : }
74 :
75 :
76 : /*--------------------------------------------------------------*
77 : * Nearest_neighbor_2D8(x,y)
78 : *
79 : * NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE 2D8
80 : * algorithm: nn_2D8(x) = 2*nn_D8(x/2)
81 : * nn_D8 = decoding of Z^8 with Wagner rule
82 : * (see Conway and Sloane's paper in IT-82)
83 : --------------------------------------------------------------*/
84 :
85 4823308 : static void nearest_neighbor_2D8_fx(
86 : const Word32 x[], /* i : point in R^8 Q15*/
87 : Word16 y[] /* o : point in 2D8 (8-dimensional integer vector) Q0*/
88 : )
89 : {
90 : Word16 i, j;
91 : Word16 sum, tmp16, tmp16b;
92 : Word32 s, e, em;
93 :
94 : /*--------------------------------------------------------------*
95 : * round x into 2Z^8 i.e. compute y=(y1,...,y8) such that yi = 2[xi/2]
96 : * where [.] is the nearest integer operator
97 : * in the mean time, compute sum = y1+...+y8
98 : *--------------------------------------------------------------*/
99 4823308 : sum = 0;
100 4823308 : move16();
101 :
102 43409772 : FOR( i = 0; i < 8; i++ )
103 : {
104 : /* round to ..., -2, 0, 2, ... ([-1..1[ --> 0) */
105 38586464 : tmp16 = round_fx( L_add( x[i], L_shr( x[i], 31 ) ) );
106 38586464 : y[i] = shl( tmp16, 1 ); /* Q0 */
107 38586464 : move16();
108 : /* sum += y[i] */
109 38586464 : sum = add( sum, y[i] ); /* Q0 */
110 : }
111 :
112 : /*--------------------------------------------------------------*
113 : * check if y1+...+y8 is a multiple of 4
114 : * if not, y is not round xj in the wrong way where j is defined by
115 : * j = arg max_i | xi -yi|
116 : * (this is called the Wagner rule)
117 : *--------------------------------------------------------------*/
118 4823308 : IF( s_and( sum, 2 ) != 0 )
119 : {
120 : /* find j = arg max_i | xi -yi| */
121 2511008 : em = L_deposit_l( 0 );
122 2511008 : j = 0;
123 2511008 : move16();
124 :
125 22599072 : FOR( i = 0; i < 8; i++ )
126 : {
127 : /* compute ei = xi-yi */
128 : /* e[i]=x[i]-y[i] */
129 20088064 : e = L_msu( x[i], y[i], QR / 2 ); /* Q15 */
130 :
131 : /* compute |ei| = | xi-yi | */
132 20088064 : s = L_abs( e );
133 :
134 : /* check if |ei| is maximal, if so, set j=i */
135 20088064 : if ( LT_32( em, s ) )
136 : {
137 5568005 : j = i;
138 5568005 : move16();
139 : }
140 20088064 : em = L_max( s, em ); /* Q15 */
141 : }
142 :
143 : /* round xj in the "wrong way" */
144 2511008 : e = L_msu( x[j], y[j], QR / 2 ); /* Q15 */
145 2511008 : tmp16 = extract_h( e );
146 2511008 : tmp16b = add( y[j], 2 ); /* Q0 */
147 :
148 2511008 : if ( tmp16 < 0 )
149 : {
150 1150305 : tmp16b = sub( tmp16b, 2 + 2 ); /* Q0 */
151 : }
152 2511008 : y[j] = tmp16b; /* Q0 */
153 2511008 : move16();
154 : }
155 :
156 4823308 : return;
157 : }
158 :
159 :
160 : /*--------------------------------------------------------------*
161 : * Compute_error_2D8(x,y)
162 : *
163 : * Compute mean square error between input vector and
164 : * (quantized) point in 2D8.
165 : --------------------------------------------------------------*/
166 :
167 4823308 : static Word32 compute_error_2D8_fx( /* o : mean squared error Q15*/
168 : const Word32 x[], /* i : input vector Q15*/
169 : const Word16 y[] /* i : point in 2D8 (8-dimensional integer vector) Q0*/
170 : )
171 : {
172 : Word16 i, hi, lo;
173 : Word32 err, Ltmp;
174 :
175 4823308 : err = L_deposit_l( 0 );
176 43409772 : FOR( i = 0; i < 8; i++ )
177 : {
178 : /*tmp = x[i]-y[i];*/
179 38586464 : Ltmp = L_msu( x[i], y[i], 16384 ); /* Q15 */
180 38586464 : hi = extract_h( L_shl( Ltmp, 1 ) ); /* Q0 */
181 38586464 : lo = extract_l( L_msu( Ltmp, hi, 16384 ) ); /* Q15 */
182 :
183 38586464 : Ltmp = L_mult( hi, hi ); /* Q1 */
184 38586464 : Ltmp = L_shl( Ltmp, 14 ); /* Q15 */
185 38586464 : Ltmp = L_mac( Ltmp, hi, lo ); /* Q15 */
186 38586464 : Ltmp = L_mac0( Ltmp, mult( lo, lo ), 1 ); /* Q15 */
187 :
188 : /* err+=tmp*tmp */
189 38586464 : err = L_add( Ltmp, err ); /* Q15 */
190 : }
191 :
192 4823308 : return ( err );
193 : }
|