comparison libtwamr/ph_disp.c @ 390:bde9f5804670

libtwamr: integrate ph_disp.c
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 06 May 2024 18:20:22 +0000
parents
children
comparison
equal deleted inserted replaced
389:9cd332a94c97 390:bde9f5804670
1 /*
2 ********************************************************************************
3 *
4 * GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001
5 * R99 Version 3.3.0
6 * REL-4 Version 4.1.0
7 *
8 ********************************************************************************
9 *
10 * File : ph_disp.c
11 * Purpose : Perform adaptive phase dispersion of the excitation
12 * signal.
13 *
14 ********************************************************************************
15 */
16 /*
17 ********************************************************************************
18 * MODULE INCLUDE FILE AND VERSION ID
19 ********************************************************************************
20 */
21 #include "namespace.h"
22 #include "ph_disp.h"
23
24 /*
25 ********************************************************************************
26 * INCLUDE FILES
27 ********************************************************************************
28 */
29 #include "typedef.h"
30 #include "basic_op.h"
31 #include "no_count.h"
32 #include "cnst.h"
33 #include "memops.h"
34
35 /*
36 ********************************************************************************
37 * LOCAL VARIABLES AND TABLES
38 ********************************************************************************
39 */
40
41 #include "ph_disp.tab"
42
43 /*
44 ********************************************************************************
45 * PUBLIC PROGRAM CODE
46 ********************************************************************************
47 */
48
49 /*************************************************************************
50 *
51 * Function: ph_disp_reset
52 *
53 **************************************************************************
54 */
55 void ph_disp_reset (ph_dispState *state)
56 {
57 Word16 i;
58
59 for (i=0; i<PHDGAINMEMSIZE; i++)
60 {
61 state->gainMem[i] = 0;
62 }
63 state->prevState = 0;
64 state->prevCbGain = 0;
65 state->lockFull = 0;
66 state->onset = 0; /* assume no onset in start */
67 }
68
69 /*************************************************************************
70 *
71 * Function: ph_disp_lock
72 *
73 **************************************************************************
74 */
75 void ph_disp_lock (ph_dispState *state)
76 {
77 state->lockFull = 1;
78 return;
79 }
80
81 /*************************************************************************
82 *
83 * Function: ph_disp_release
84 *
85 **************************************************************************
86 */
87 void ph_disp_release (ph_dispState *state)
88 {
89 state->lockFull = 0;
90 return;
91 }
92
93
94 /*************************************************************************
95 *
96 * Function: ph_disp
97 *
98 * Adaptive phase dispersion; forming of total excitation
99 * (for synthesis part of decoder)
100 *
101 **************************************************************************
102 */
103 void ph_disp (
104 ph_dispState *state, /* i/o : State struct */
105 enum Mode mode, /* i : codec mode */
106 Word16 x[], /* i/o Q0 : in: LTP excitation signal */
107 /* out: total excitation signal */
108 Word16 cbGain, /* i Q1 : Codebook gain */
109 Word16 ltpGain, /* i Q14 : LTP gain */
110 Word16 inno[], /* i/o Q13 : Innovation vector (Q12 for 12.2) */
111 Word16 pitch_fac, /* i Q14 : pitch factor used to scale the
112 LTP excitation (Q13 for 12.2) */
113 Word16 tmp_shift /* i Q0 : shift factor applied to sum of
114 scaled LTP ex & innov. before
115 rounding */
116 )
117 {
118 Word16 i, i1;
119 Word16 tmp1;
120 Word32 L_temp;
121 Word16 impNr; /* indicator for amount of disp./filter used */
122
123 Word16 inno_sav[L_SUBFR];
124 Word16 ps_poss[L_SUBFR];
125 Word16 j, nze, nPulse, ppos;
126 const Word16 *ph_imp; /* Pointer to phase dispersion filter */
127
128 /* Update LTP gain memory */
129 for (i = PHDGAINMEMSIZE-1; i > 0; i--)
130 {
131 state->gainMem[i] = state->gainMem[i-1]; move16 ();
132 }
133 state->gainMem[0] = ltpGain; move16 ();
134
135 /* basic adaption of phase dispersion */
136 test ();
137 if (sub(ltpGain, PHDTHR2LTP) < 0) { /* if (ltpGain < 0.9) */
138 test ();
139 if (sub(ltpGain, PHDTHR1LTP) > 0)
140 { /* if (ltpGain > 0.6 */
141 impNr = 1; /* medium dispersion */ move16 ();
142 }
143 else
144 {
145 impNr = 0; /* maximum dispersion */ move16 ();
146 }
147 }
148 else
149 {
150 impNr = 2; /* no dispersion */ move16 ();
151 }
152
153 /* onset indicator */
154 /* onset = (cbGain > onFact * cbGainMem[0]) */
155 move32 ();
156 tmp1 = round(L_shl(L_mult(state->prevCbGain, ONFACTPLUS1), 2));
157 test ();
158 if (sub(cbGain, tmp1) > 0)
159 {
160 state->onset = ONLENGTH; move16 ();
161 }
162 else
163 {
164 test ();
165 if (state->onset > 0)
166 {
167 state->onset = sub (state->onset, 1); move16 ();
168 }
169 }
170
171 /* if not onset, check ltpGain buffer and use max phase dispersion if
172 half or more of the ltpGain-parameters say so */
173 test ();
174 if (state->onset == 0)
175 {
176 /* Check LTP gain memory and set filter accordingly */
177 i1 = 0; move16 ();
178 for (i = 0; i < PHDGAINMEMSIZE; i++)
179 {
180 test ();
181 if (sub(state->gainMem[i], PHDTHR1LTP) < 0)
182 {
183 i1 = add (i1, 1);
184 }
185 }
186 test ();
187 if (sub(i1, 2) > 0)
188 {
189 impNr = 0; move16 ();
190 }
191
192 }
193 /* Restrict decrease in phase dispersion to one step if not onset */
194 test (); test ();
195 if ((sub(impNr, add(state->prevState, 1)) > 0) && (state->onset == 0))
196 {
197 impNr = sub (impNr, 1);
198 }
199 /* if onset, use one step less phase dispersion */
200 test (); test ();
201 if((sub(impNr, 2) < 0) && (state->onset > 0))
202 {
203 impNr = add (impNr, 1);
204 }
205
206 /* disable for very low levels */
207 test ();
208 if(sub(cbGain, 10) < 0)
209 {
210 impNr = 2; move16 ();
211 }
212
213 test ();
214 if(sub(state->lockFull, 1) == 0)
215 {
216 impNr = 0; move16 ();
217 }
218
219 /* update static memory */
220 state->prevState = impNr; move16 ();
221 state->prevCbGain = cbGain; move16 ();
222
223 /* do phase dispersion for all modes but 12.2 and 7.4;
224 don't modify the innovation if impNr >=2 (= no phase disp) */
225 test (); test (); test(); test();
226 if (sub(mode, MR122) != 0 &&
227 sub(mode, MR102) != 0 &&
228 sub(mode, MR74) != 0 &&
229 sub(impNr, 2) < 0)
230 {
231 /* track pulse positions, save innovation,
232 and initialize new innovation */
233 nze = 0; move16 ();
234 for (i = 0; i < L_SUBFR; i++)
235 {
236 move16 (); test();
237 if (inno[i] != 0)
238 {
239 ps_poss[nze] = i; move16 ();
240 nze = add (nze, 1);
241 }
242 inno_sav[i] = inno[i]; move16 ();
243 inno[i] = 0; move16 ();
244 }
245 /* Choose filter corresponding to codec mode and dispersion criterium */
246 test ();
247 if (sub (mode, MR795) == 0)
248 {
249 test ();
250 if (impNr == 0)
251 {
252 ph_imp = ph_imp_low_MR795; move16 ();
253 }
254 else
255 {
256 ph_imp = ph_imp_mid_MR795; move16 ();
257 }
258 }
259 else
260 {
261 test ();
262 if (impNr == 0)
263 {
264 ph_imp = ph_imp_low; move16 ();
265 }
266 else
267 {
268 ph_imp = ph_imp_mid; move16 ();
269 }
270 }
271
272 /* Do phase dispersion of innovation */
273 for (nPulse = 0; nPulse < nze; nPulse++)
274 {
275 ppos = ps_poss[nPulse]; move16 ();
276
277 /* circular convolution with impulse response */
278 j = 0; move16 ();
279 for (i = ppos; i < L_SUBFR; i++)
280 {
281 /* inno[i1] += inno_sav[ppos] * ph_imp[i1-ppos] */
282 tmp1 = mult(inno_sav[ppos], ph_imp[j++]);
283 inno[i] = add(inno[i], tmp1); move16 ();
284 }
285
286 for (i = 0; i < ppos; i++)
287 {
288 /* inno[i] += inno_sav[ppos] * ph_imp[L_SUBFR-ppos+i] */
289 tmp1 = mult(inno_sav[ppos], ph_imp[j++]);
290 inno[i] = add(inno[i], tmp1); move16 ();
291 }
292 }
293 }
294
295 /* compute total excitation for synthesis part of decoder
296 (using modified innovation if phase dispersion is active) */
297 for (i = 0; i < L_SUBFR; i++)
298 {
299 /* x[i] = gain_pit*x[i] + cbGain*code[i]; */
300 L_temp = L_mult ( x[i], pitch_fac);
301 /* 12.2: Q0 * Q13 */
302 /* 7.4: Q0 * Q14 */
303 L_temp = L_mac (L_temp, inno[i], cbGain);
304 /* 12.2: Q12 * Q1 */
305 /* 7.4: Q13 * Q1 */
306 L_temp = L_shl (L_temp, tmp_shift); /* Q16 */
307 x[i] = round (L_temp); move16 ();
308 }
309
310 return;
311 }