Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 : #include <stdint.h>
5 : #include "options.h" /* Compilation switches */
6 : #include "cnst.h" /* Common constants */
7 : //#include "prot_fx.h"
8 : #include "rom_com_fx.h"
9 : #include "cnst.h"
10 : #include "rom_com.h" /* Common constants */
11 : #include "prot_fx.h" /* Function prototypes */
12 : #include "prot_fx_enc.h" /* Function prototypes */
13 : #include "basop_util.h" /* Function prototypes */
14 :
15 : /*---------------------------------------------------------------------*
16 : * hf_cod_init()
17 : *
18 : *
19 : *---------------------------------------------------------------------*/
20 3 : void hf_cod_init_fx(
21 : Word16 *mem_hp400_enc, /* o: memory of hp 400 Hz filter */
22 : Word16 *mem_hf1_enc, /* o: HF band-pass filter memory */
23 : Word16 *mem_syn_hf_enc, /* o: HF synthesis memory */
24 : Word16 *mem_hf2_enc, /* o: HF band-pass filter memory */
25 : Word16 *gain_alpha_fx /* o: smoothing gain for transitions between active and inactive frames */
26 : )
27 : {
28 3 : set16_fx( mem_hp400_enc, 0, 6 );
29 3 : set16_fx( mem_hf1_enc, 0, L_FIR - 1 );
30 3 : set16_fx( mem_syn_hf_enc, 0, M );
31 3 : set16_fx( mem_hf2_enc, 0, L_FIR - 1 );
32 :
33 3 : *gain_alpha_fx = 16384;
34 3 : move16();
35 :
36 3 : return;
37 : }
38 :
39 : /*---------------------------------------------------------------------*
40 : * hf_cod()
41 : *
42 : *
43 : *---------------------------------------------------------------------*/
44 :
45 0 : void hf_cod_fx(
46 : const Word32 core_brate_fx, /* i : core bitrate */
47 : const Word16 *speech16k_fx, /* i : original speech at 16 kHz */
48 : const Word16 Aq_fx[], /* i : quantized Aq */
49 : const Word16 exc_fx[], /* i : excitation at 12.8 kHz */
50 : Word16 synth_fx[], /* i : 12.8kHz synthesis signal */
51 : Word16 *seed2_enc_fx, /* i/o: random seed for HF noise gen */
52 : Word16 *mem_hp400_enc_fx, /* i/o: memory of hp 400 Hz filter */
53 : Word16 *mem_syn_hf_enc_fx, /* i/o: HF synthesis memory */
54 : Word16 *mem_hf1_enc_fx, /* i/o: HF band-pass filter memory */
55 : Word16 *mem_hf2_enc_fx, /* i/o: HF band-pass filter memory */
56 : const Word16 dtxHangoverCount_fx,
57 : Word16 *gain_alpha_fx, /* i/o: smoothing gain for transitions between active and inactive frames */
58 : Word16 *hf_gain_fx, /* o : HF gain to be transmitted to decoder */
59 : Word16 Q_exc,
60 : Word16 Q_syn )
61 : {
62 : /*------------------------Scaling-------------------------------------------------
63 : speech16k - Q0
64 : Aq - Q12
65 : exc - Q_exc
66 : synth - Q_syn
67 : mem_hp400_enc - Q_syn
68 : mem_syn_hf_enc - Q0
69 : mem_hf1_enc - Q0
70 : mem_hf2_enc - Q0
71 : gain_alpha_fx - Q14
72 : ener - all dynamic
73 : fac, scale - Q12
74 : Ap - Q12
75 : HF_SP - Q0
76 : ---------------------------------------------------------------------------------*/
77 :
78 : Word16 i, q1, q2, sign;
79 : Word16 shift;
80 : Word16 ener_hf_fx, ener_exc_fx, ener_input_fx, fac_fx, tmp_fx, ener_fx, scale_fx;
81 : Word16 Ap_fx[M + 1];
82 : Word16 HF_SP_fx[L_SUBFR16k];
83 : Word16 HF_est_gain_fx, HF_calc_gain_fx, HF_corr_gain_fx, HF_gain_ind_fx;
84 : Word32 dist_min_fx, dist_fx;
85 : Word16 HF_fx[L_SUBFR16k], HF_syn_fx[L_SUBFR16k]; /* o : HF excitation */
86 : Word32 L_tmp;
87 : Word16 *pt1;
88 : const Word16 *pt2;
89 : #ifndef ISSUE_1867_replace_overflow_libenc
90 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
91 : Flag Overflow = 0;
92 : #endif
93 : #endif
94 :
95 : /* Original speech signal as reference for high band gain quantisation */
96 0 : Copy( speech16k_fx, HF_SP_fx, L_SUBFR16k );
97 :
98 : /*-----------------------------------------------------------------*
99 : * generate white noise vector
100 : *-----------------------------------------------------------------*/
101 :
102 0 : Random_Fill( seed2_enc_fx, L_SUBFR16k, HF_fx, 3 ); /*Q(-3) */
103 :
104 : /*-----------------------------------------------------------------*
105 : * calculate energy scaling factor so that white noise would have the
106 : * same energy as exc12k8
107 : *-----------------------------------------------------------------*/
108 :
109 0 : ener_exc_fx = dot_prod_satcontr( exc_fx, exc_fx, Q_exc, Q_exc, &q1, L_SUBFR );
110 0 : ener_hf_fx = dot_prod_satcontr( HF_fx, HF_fx, -3, -3, &q2, L_SUBFR16k );
111 :
112 0 : scale_fx = div_s( shl( 1, 14 ), ener_exc_fx ); /*Q(29-q1) */
113 0 : L_tmp = L_mult( ener_hf_fx, scale_fx ); /*30-q1+q2 */
114 0 : q2 = sub( q1, q2 ); /*30-q2 */
115 : #ifdef ISSUE_1867_replace_overflow_libenc
116 0 : scale_fx = round_fx( Isqrt( L_shl_sat( L_tmp, sub( q2, 26 ) ) ) ); /*Q13 */
117 : #else
118 : scale_fx = round_fx( Isqrt( L_shl_o( L_tmp, sub( q2, 26 ), &Overflow ) ) ); /*Q13 */
119 : #endif
120 :
121 :
122 0 : pt1 = HF_fx;
123 0 : FOR( i = 0; i < L_SUBFR16k; i++ )
124 : {
125 0 : *pt1 = round_fx( L_shl( L_mult( ( *pt1 ), scale_fx ), 5 ) ); /*Q0 */
126 0 : pt1++;
127 : }
128 :
129 : /*-----------------------------------------------------------------*
130 : * calculate energy scaling factor to respect tilt of synth12k8
131 : * (tilt: 1=voiced, -1=unvoiced)
132 : *-----------------------------------------------------------------*/
133 :
134 0 : hp400_12k8_fx( synth_fx, L_SUBFR, mem_hp400_enc_fx ); /*synth_fx: Q(Q_syn-4) */
135 :
136 0 : ener_fx = dot_prod_satcontr( &synth_fx[1], &synth_fx[1], sub( Q_syn, 4 ), sub( Q_syn, 4 ), &q1, sub( L_SUBFR, 1 ) );
137 0 : tmp_fx = dot_prod_satcontr( &synth_fx[1], synth_fx, sub( Q_syn, 4 ), sub( Q_syn, 4 ), &q2, sub( L_SUBFR, 1 ) );
138 :
139 0 : IF( GE_16( abs_s( tmp_fx ), ener_fx ) )
140 : {
141 0 : tmp_fx = shr( tmp_fx, 1 );
142 0 : q2 = sub( q2, 1 );
143 : }
144 :
145 0 : sign = 0;
146 0 : move16();
147 0 : IF( tmp_fx < 0 )
148 : {
149 0 : tmp_fx = abs_s( tmp_fx );
150 0 : sign = 1;
151 0 : move16();
152 : }
153 :
154 0 : fac_fx = div_s( tmp_fx, ener_fx ); /*Q(15+q2-q1) */
155 0 : shift = sub( q1, add( q2, 5 ) );
156 0 : fac_fx = shl( fac_fx, shift ); /*Q10 */
157 0 : IF( sign )
158 : {
159 0 : fac_fx = s_xor( fac_fx, -1 );
160 : }
161 :
162 0 : HF_est_gain_fx = sub( 1024, fac_fx ); /*Q12 */
163 :
164 0 : test();
165 0 : IF( EQ_32( core_brate_fx, SID_1k75 ) || core_brate_fx == FRAME_NO_DATA )
166 : {
167 0 : HF_est_gain_fx = round_fx( L_shl( L_mult( HF_est_gain_fx, 20480 ), 1 ) ); /*Q10 */
168 : }
169 :
170 0 : HF_est_gain_fx = s_max( HF_est_gain_fx, 102 );
171 0 : HF_est_gain_fx = s_min( HF_est_gain_fx, 1024 );
172 :
173 : /*-----------------------------------------------------------------*
174 : * synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz
175 : *-----------------------------------------------------------------*/
176 :
177 0 : weight_a_lc_fx( Aq_fx, Ap_fx, Gamma_19661_Tbl_fx, M );
178 0 : Syn_filt_s( 0, Ap_fx, M, HF_fx, HF_syn_fx, L_SUBFR16k, mem_syn_hf_enc_fx, 1 ); /*Q0 */
179 :
180 : /*-----------------------------------------------------------------*
181 : * high pass filtering (0.9375ms of delay = 15 samples@16k)
182 : *-----------------------------------------------------------------*/
183 :
184 0 : fir_fx( HF_syn_fx, fir_6k_8k_fx, HF_syn_fx, mem_hf1_enc_fx, L_SUBFR16k, L_FIR - 1, 1, 0 );
185 0 : fir_fx( HF_SP_fx, fir_6k_8k_fx, HF_SP_fx, mem_hf2_enc_fx, L_SUBFR16k, L_FIR - 1, 1, 0 );
186 :
187 : /* check the gain difference */
188 :
189 0 : ener_hf_fx = dot_prod_satcontr( HF_syn_fx, HF_syn_fx, 0, 0, &q2, L_SUBFR16k );
190 0 : ener_input_fx = dot_prod_satcontr( HF_SP_fx, HF_SP_fx, 0, 0, &q1, L_SUBFR16k );
191 :
192 0 : HF_calc_gain_fx = div_s( shl( 1, 14 ), ener_input_fx ); /*Q(29-q1) */
193 0 : L_tmp = L_mult( ener_hf_fx, HF_calc_gain_fx ); /*30-q1+q2 */
194 0 : q2 = sub( q1, q2 ); /*30-q2 */
195 : #ifdef ISSUE_1867_replace_overflow_libenc
196 0 : HF_calc_gain_fx = round_fx_sat( Isqrt( L_shl_sat( L_tmp, sub( q2, 20 ) ) ) ); /*Q10 */
197 : #else
198 : HF_calc_gain_fx = round_fx_o( Isqrt( L_shl_sat( L_tmp, sub( q2, 20 ) ) ), &Overflow ); /*Q10 */
199 : #endif
200 :
201 :
202 : /* set energy of HF synthesis to energy of original HF:
203 : cross-fade between HF levels in active and inactive frame in hangover period */
204 :
205 0 : IF( GT_16( 4, dtxHangoverCount_fx ) )
206 : {
207 0 : *gain_alpha_fx = 16384;
208 0 : move16();
209 : }
210 : ELSE
211 : {
212 0 : L_tmp = L_shl( L_mult( sub( 10, dtxHangoverCount_fx ), 4681 ), 15 ); /*Q31 */
213 0 : L_tmp = Mult_32_16( L_tmp, *gain_alpha_fx ); /*Q30 */
214 0 : *gain_alpha_fx = round_fx( L_tmp ); /*Q14 */
215 : }
216 0 : L_tmp = L_mult( sub( 16384, *gain_alpha_fx ), HF_est_gain_fx ); /*Q25 */
217 0 : L_tmp = L_mac( L_tmp, *gain_alpha_fx, HF_calc_gain_fx ); /*Q25 */
218 0 : IF( GE_32( L_tmp, 67108863 ) )
219 : {
220 0 : L_tmp = 67108863;
221 0 : move32();
222 : }
223 0 : L_tmp = L_shl( L_tmp, 5 );
224 0 : HF_corr_gain_fx = extract_h( L_tmp ); /*Q14; HF_corr_gain_fx/2 in Q15 */
225 :
226 : /* Quantize the correction gain */
227 0 : dist_min_fx = 2147483647;
228 0 : move32();
229 0 : HF_gain_ind_fx = 0;
230 0 : move16();
231 0 : pt2 = HP_gain_fx;
232 0 : FOR( i = 0; i < 16; i++ )
233 : {
234 0 : dist_fx = L_mult( sub( HF_corr_gain_fx, *pt2 ), sub( HF_corr_gain_fx, *pt2 ) );
235 0 : pt2++;
236 0 : IF( GT_32( dist_min_fx, dist_fx ) )
237 : {
238 0 : dist_min_fx = L_add( dist_fx, 0 );
239 0 : HF_gain_ind_fx = i;
240 0 : move16();
241 : }
242 : }
243 0 : *hf_gain_fx = HF_gain_ind_fx;
244 0 : move16();
245 :
246 0 : return;
247 : }
|