Line data Source code
1 : /******************************************************************************
2 : * ETSI TS 103 634 V1.5.1 *
3 : * Low Complexity Communication Codec Plus (LC3plus) *
4 : * *
5 : * Copyright licence is solely granted through ETSI Intellectual Property *
6 : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
7 : * estoppel or otherwise. *
8 : ******************************************************************************/
9 :
10 : #include "defines.h"
11 : #include "functions.h"
12 :
13 0 : void processPLCupdate_fx(AplcSetup *plcAd, Word16 x_fx[], Word16 q_fx_exp, Word16 concealMethod, Word16 frame_length,
14 : Word16 fs_idx, Word16 *nbLostFramesInRow, Word16 *prev_prev_bfi, Word16 *prev_bfi, Word16 bfi, Word16 scf_q[],
15 : Word16 *ns_cum_alpha
16 : #ifdef ENABLE_HR_MODE
17 : , Word16 hrmode
18 : #endif
19 : )
20 : {
21 0 : processPLCUpdateAfterIMDCT_fx(x_fx, q_fx_exp, concealMethod, frame_length, fs_idx, nbLostFramesInRow, prev_prev_bfi, prev_bfi, bfi,
22 : scf_q, ns_cum_alpha, plcAd); /* NB *prev_bfi updated here */
23 :
24 0 : IF ( plcAd != 0 )
25 : {
26 : /* reuse/inplace the most recent 16 ms of x_old_tot without additional rescaling, keep exponent aligned with tdc pitch buffer to save WMOPS */
27 :
28 :
29 : #ifdef ENABLE_HR_MODE
30 0 : if (hrmode == 0)
31 : #endif
32 : {
33 0 : ASSERT( (&plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - LprotSzPtr[fs_idx] ]) == plcAd->PhECU_xfp_fx );
34 0 : plcAd->PhECU_xfp_exp_fx = plcAd->q_fx_old_exp; move16(); /* exponent used by concealmethod 2 in prevBfi frames and also right after non bfi frames */
35 : }
36 : }
37 0 : }
38 :
39 0 : void processPLCupdateSpec_fx(Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], Word16 *q_fx_exp, Word16 yLen)
40 : {
41 : Dyn_Mem_Deluxe_In(
42 : Counter i;
43 : Word16 s;
44 : );
45 :
46 : /* save spectrum and the corresponding exponent */
47 0 : s = getScaleFactor32_lc3plus(q_d_fx, yLen);
48 :
49 0 : *q_old_fx_exp = sub(*q_fx_exp, s);
50 :
51 :
52 0 : FOR (i = 0; i < yLen; i++)
53 : {
54 0 : q_old_d_fx[i] = round_fx_sat(L_shl_sat(q_d_fx[i], s)); /* */
55 : }
56 :
57 : Dyn_Mem_Deluxe_Out();
58 0 : }
59 :
60 0 : void processPLCspec2shape_fx(Word16 prev_bfi, Word16 bfi, Word16 q_old_d_fx[], Word16 yLen,
61 : Word16 *stPhECU_oold_grp_shape_fx, Word16 *stPhECU_old_grp_shape_fx)
62 :
63 : #define L_GRP_DC 4
64 :
65 : {
66 : Counter i,l;
67 : Word16 *pX, tmp;
68 : Word16 N_grp,l_grp;
69 : Word16 man, expo;
70 : Word32 L_acc;
71 : Word32 L_tot;
72 : Word32 L_grp_shape[MAX_LGW];
73 : Word16 grp_shape[MAX_LGW]; /**/
74 : Word16 fs_idx,local_prev_bfi;
75 :
76 :
77 : #ifdef DYNMEM_COUNT
78 : Dyn_Mem_In("process_plc_spec_2_shape_fx", sizeof(struct {
79 : Counter i,l;
80 : Word16 *pX;
81 : Word16 N_grp,l_grp;
82 : Word32 L_acc;
83 : Word32 L_tot;
84 : Word32 L_grp_shape[MAX_LGW];
85 : Word16 fs_idx,local_prev_bfi;
86 : }));
87 : #endif
88 : #ifdef WMOPS
89 : push_wmops("PhECU::GF::process_plc_spec_2_shape_fx");
90 : #endif
91 :
92 0 : IF(sub(bfi, 1) != 0)
93 : {
94 0 : fs_idx = mult(yLen, (Word16)(32768.0 / (99.0))); /* truncation needed , i.e no rounding can be applied here */
95 0 : N_grp = xavg_N_grp_fx[fs_idx]; move16();
96 :
97 0 : local_prev_bfi = prev_bfi; move16();
98 0 : if (sub(local_prev_bfi, 2)==0)
99 : {
100 0 : local_prev_bfi = 0; move16();
101 : }
102 :
103 0 : if( stPhECU_oold_grp_shape_fx[0] < 0 )
104 : {
105 0 : local_prev_bfi = 1 ; move16(); /* handle startup in the case 2nd frame is a BFI frame */
106 : }
107 :
108 : /* Copy old to oold grp shape */
109 0 : FOR( i=0; i < MAX_LGW ; i++)
110 : {
111 0 : stPhECU_oold_grp_shape_fx[i] = stPhECU_old_grp_shape_fx[i]; move16();
112 : }
113 :
114 :
115 : /* Accumulate DC bin(s) to total */
116 0 : pX = q_old_d_fx; /* ptr setup */
117 0 : L_tot = L_deposit_h(0); /* acc on negative side */
118 :
119 0 : FOR( i= 0; i < L_GRP_DC; i++)
120 : {
121 0 : tmp = shr_pos(*pX++ ,spec_shape_headroom[fs_idx]); /* scale down upscaled MDCT to create some headroom */
122 0 : L_tot = L_msu0(L_tot, tmp, tmp);
123 :
124 : }
125 :
126 : /* Accumulate middle subbands and add to total */
127 0 : FOR( i=0; i < sub(N_grp,1) ; i++)
128 : {
129 :
130 0 : L_acc = L_deposit_h(0); /* acc on negative side */
131 0 : l_grp = sub(mdct_grp_bins_fx[i+1], mdct_grp_bins_fx[i]); move16();
132 :
133 :
134 :
135 0 : FOR(l=0;l<l_grp; l++)
136 : {
137 0 : tmp = shr(*pX++ ,spec_shape_headroom[fs_idx]);
138 0 : L_acc = L_msu0(L_acc, tmp, tmp);
139 :
140 : }
141 :
142 :
143 0 : L_grp_shape[i] = L_negate(L_acc); move32();
144 0 : L_tot = L_add(L_tot, L_acc); move32(); /* two negative numbers added */
145 : }
146 :
147 : /* Accumulate last subbband and add to total */
148 :
149 0 : L_acc = L_deposit_h(0);
150 0 : l_grp = sub(sub(mdct_grp_bins_fx[N_grp], mdct_grp_bins_fx[N_grp-1]),L_GRP_DC);
151 :
152 :
153 0 : FOR(l=0; l<l_grp; l++)
154 : {
155 0 : tmp = shr(*pX++, spec_shape_headroom[fs_idx]);
156 0 : L_acc = L_msu0(L_acc, tmp, tmp);
157 :
158 : }
159 :
160 :
161 0 : L_grp_shape[sub(N_grp,1)] = L_negate(L_acc); move32();
162 :
163 :
164 0 : L_tot = L_add(L_tot, L_acc); /* two negative numbers added */
165 :
166 0 : L_tot = L_max( -(INT32_MAX), L_tot); /* conditionally add 1 to negative side, to avoid possible saturation in L_negate */
167 0 : L_tot = L_negate(L_tot); /* no saturation here as L_tot is != INT_MIN */
168 :
169 :
170 : /* Normalize shape */
171 : /* norm_scale = 1/L_tot; */
172 :
173 0 : IF (L_tot > 0)
174 : {
175 0 : FOR(i=0; i < N_grp ; i++)
176 : {
177 0 : man = plc_phEcu_ratio_fx(L_grp_shape[i], L_tot, &expo); /* The mantissa is considered in Q15 output in Q14 */
178 0 : grp_shape[i] = shr_sat(man, sub(expo,1)); /* gfrom Q14 to in Q15 (Due to saturation, it is automatically bound inside [-1.0,1.0].) */
179 : }
180 : }
181 : ELSE
182 : {
183 0 : FOR(i=0; i < N_grp ; i++)
184 : {
185 0 : grp_shape[i] = GRP_SHAPE_INIT; move16();
186 :
187 : }
188 : }
189 :
190 : /* copy to output */
191 0 : FOR(i=0; i < N_grp ; i++)
192 : {
193 0 : stPhECU_old_grp_shape_fx[i] = grp_shape[i]; move16();
194 : }
195 0 : FOR(i = N_grp; i < MAX_LGW ; i++)
196 : {
197 0 : stPhECU_old_grp_shape_fx[i] = GRP_SHAPE_INIT; move16();
198 : }
199 :
200 :
201 :
202 : /* handle oold states for the frame sequence BAD, GOOD, NEXT_BAD */
203 0 : if(sub(local_prev_bfi, 1)==0)
204 : {
205 0 : FOR( i=0; i < MAX_LGW ; i++)
206 : {
207 0 : stPhECU_oold_grp_shape_fx[i] = stPhECU_old_grp_shape_fx[i] ; move16();
208 : }
209 : }
210 :
211 : }
212 :
213 : #ifdef WMOPS
214 : pop_wmops();
215 : #endif
216 : #ifdef DYNMEM_COUNT
217 : Dyn_Mem_Out();
218 : #endif
219 :
220 0 : }
221 :
222 :
223 :
224 :
|