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 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
90 0 : Flag Overflow = 0;
91 : #endif
92 :
93 : /* Original speech signal as reference for high band gain quantisation */
94 0 : Copy( speech16k_fx, HF_SP_fx, L_SUBFR16k );
95 :
96 : /*-----------------------------------------------------------------*
97 : * generate white noise vector
98 : *-----------------------------------------------------------------*/
99 :
100 0 : Random_Fill( seed2_enc_fx, L_SUBFR16k, HF_fx, 3 ); /*Q(-3) */
101 :
102 : /*-----------------------------------------------------------------*
103 : * calculate energy scaling factor so that white noise would have the
104 : * same energy as exc12k8
105 : *-----------------------------------------------------------------*/
106 :
107 0 : ener_exc_fx = dot_prod_satcontr( exc_fx, exc_fx, Q_exc, Q_exc, &q1, L_SUBFR );
108 0 : ener_hf_fx = dot_prod_satcontr( HF_fx, HF_fx, -3, -3, &q2, L_SUBFR16k );
109 :
110 0 : scale_fx = div_s( shl( 1, 14 ), ener_exc_fx ); /*Q(29-q1) */
111 0 : L_tmp = L_mult( ener_hf_fx, scale_fx ); /*30-q1+q2 */
112 0 : q2 = sub( q1, q2 ); /*30-q2 */
113 0 : scale_fx = round_fx( Isqrt( L_shl_o( L_tmp, sub( q2, 26 ), &Overflow ) ) ); /*Q13 */
114 :
115 :
116 0 : pt1 = HF_fx;
117 0 : FOR( i = 0; i < L_SUBFR16k; i++ )
118 : {
119 0 : *pt1 = round_fx( L_shl( L_mult( ( *pt1 ), scale_fx ), 5 ) ); /*Q0 */
120 0 : pt1++;
121 : }
122 :
123 : /*-----------------------------------------------------------------*
124 : * calculate energy scaling factor to respect tilt of synth12k8
125 : * (tilt: 1=voiced, -1=unvoiced)
126 : *-----------------------------------------------------------------*/
127 :
128 0 : hp400_12k8_fx( synth_fx, L_SUBFR, mem_hp400_enc_fx ); /*synth_fx: Q(Q_syn-4) */
129 :
130 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 ) );
131 0 : tmp_fx = dot_prod_satcontr( &synth_fx[1], synth_fx, sub( Q_syn, 4 ), sub( Q_syn, 4 ), &q2, sub( L_SUBFR, 1 ) );
132 :
133 0 : IF( GE_16( abs_s( tmp_fx ), ener_fx ) )
134 : {
135 0 : tmp_fx = shr( tmp_fx, 1 );
136 0 : q2 = sub( q2, 1 );
137 : }
138 :
139 0 : sign = 0;
140 0 : move16();
141 0 : IF( tmp_fx < 0 )
142 : {
143 0 : tmp_fx = abs_s( tmp_fx );
144 0 : sign = 1;
145 0 : move16();
146 : }
147 :
148 0 : fac_fx = div_s( tmp_fx, ener_fx ); /*Q(15+q2-q1) */
149 0 : shift = sub( q1, add( q2, 5 ) );
150 0 : fac_fx = shl( fac_fx, shift ); /*Q10 */
151 0 : IF( sign )
152 : {
153 0 : fac_fx = s_xor( fac_fx, -1 );
154 : }
155 :
156 0 : HF_est_gain_fx = sub( 1024, fac_fx ); /*Q12 */
157 :
158 0 : test();
159 0 : IF( EQ_32( core_brate_fx, SID_1k75 ) || core_brate_fx == FRAME_NO_DATA )
160 : {
161 0 : HF_est_gain_fx = round_fx( L_shl( L_mult( HF_est_gain_fx, 20480 ), 1 ) ); /*Q10 */
162 : }
163 :
164 0 : HF_est_gain_fx = s_max( HF_est_gain_fx, 102 );
165 0 : HF_est_gain_fx = s_min( HF_est_gain_fx, 1024 );
166 :
167 : /*-----------------------------------------------------------------*
168 : * synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz
169 : *-----------------------------------------------------------------*/
170 :
171 0 : weight_a_lc_fx( Aq_fx, Ap_fx, Gamma_19661_Tbl_fx, M );
172 0 : Syn_filt_s( 0, Ap_fx, M, HF_fx, HF_syn_fx, L_SUBFR16k, mem_syn_hf_enc_fx, 1 ); /*Q0 */
173 :
174 : /*-----------------------------------------------------------------*
175 : * high pass filtering (0.9375ms of delay = 15 samples@16k)
176 : *-----------------------------------------------------------------*/
177 :
178 0 : fir_fx( HF_syn_fx, fir_6k_8k_fx, HF_syn_fx, mem_hf1_enc_fx, L_SUBFR16k, L_FIR - 1, 1, 0 );
179 0 : fir_fx( HF_SP_fx, fir_6k_8k_fx, HF_SP_fx, mem_hf2_enc_fx, L_SUBFR16k, L_FIR - 1, 1, 0 );
180 :
181 : /* check the gain difference */
182 :
183 0 : ener_hf_fx = dot_prod_satcontr( HF_syn_fx, HF_syn_fx, 0, 0, &q2, L_SUBFR16k );
184 0 : ener_input_fx = dot_prod_satcontr( HF_SP_fx, HF_SP_fx, 0, 0, &q1, L_SUBFR16k );
185 :
186 0 : HF_calc_gain_fx = div_s( shl( 1, 14 ), ener_input_fx ); /*Q(29-q1) */
187 0 : L_tmp = L_mult( ener_hf_fx, HF_calc_gain_fx ); /*30-q1+q2 */
188 0 : q2 = sub( q1, q2 ); /*30-q2 */
189 0 : HF_calc_gain_fx = round_fx_o( Isqrt( L_shl_sat( L_tmp, sub( q2, 20 ) ) ), &Overflow ); /*Q10 */
190 :
191 :
192 : /* set energy of HF synthesis to energy of original HF:
193 : cross-fade between HF levels in active and inactive frame in hangover period */
194 :
195 0 : IF( GT_16( 4, dtxHangoverCount_fx ) )
196 : {
197 0 : *gain_alpha_fx = 16384;
198 0 : move16();
199 : }
200 : ELSE
201 : {
202 0 : L_tmp = L_shl( L_mult( sub( 10, dtxHangoverCount_fx ), 4681 ), 15 ); /*Q31 */
203 0 : L_tmp = Mult_32_16( L_tmp, *gain_alpha_fx ); /*Q30 */
204 0 : *gain_alpha_fx = round_fx( L_tmp ); /*Q14 */
205 : }
206 0 : L_tmp = L_mult( sub( 16384, *gain_alpha_fx ), HF_est_gain_fx ); /*Q25 */
207 0 : L_tmp = L_mac( L_tmp, *gain_alpha_fx, HF_calc_gain_fx ); /*Q25 */
208 0 : IF( GE_32( L_tmp, 67108863 ) )
209 : {
210 0 : L_tmp = 67108863;
211 0 : move32();
212 : }
213 0 : L_tmp = L_shl( L_tmp, 5 );
214 0 : HF_corr_gain_fx = extract_h( L_tmp ); /*Q14; HF_corr_gain_fx/2 in Q15 */
215 :
216 : /* Quantize the correction gain */
217 0 : dist_min_fx = 2147483647;
218 0 : move32();
219 0 : HF_gain_ind_fx = 0;
220 0 : move16();
221 0 : pt2 = HP_gain_fx;
222 0 : FOR( i = 0; i < 16; i++ )
223 : {
224 0 : dist_fx = L_mult( sub( HF_corr_gain_fx, *pt2 ), sub( HF_corr_gain_fx, *pt2 ) );
225 0 : pt2++;
226 0 : IF( GT_32( dist_min_fx, dist_fx ) )
227 : {
228 0 : dist_min_fx = L_add( dist_fx, 0 );
229 0 : HF_gain_ind_fx = i;
230 0 : move16();
231 : }
232 : }
233 0 : *hf_gain_fx = HF_gain_ind_fx;
234 0 : move16();
235 :
236 0 : return;
237 : }
|