comparison libtwamr/cod_amr.c @ 418:93d6c6960a46

libtwamr: integrate cod_amr.c
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 07 May 2024 03:50:25 +0000
parents
children
comparison
equal deleted inserted replaced
417:f17e42c63058 418:93d6c6960a46
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 : cod_amr.c
11 * Purpose : Main encoder routine operating on a frame basis.
12 *
13 *****************************************************************************
14 */
15 #include "namespace.h"
16 #include "cod_amr.h"
17
18 /*
19 *****************************************************************************
20 * INCLUDE FILES
21 *****************************************************************************
22 */
23
24 #include "typedef.h"
25 #include "basic_op.h"
26 #include "no_count.h"
27 #include "cnst.h"
28 #include "memops.h"
29 #include "qua_gain.h"
30
31 #include "lpc.h"
32 #include "lsp.h"
33 #include "pre_big.h"
34 #include "ol_ltp.h"
35 #include "p_ol_wgh.h"
36 #include "spreproc.h"
37 #include "cl_ltp.h"
38 #include "pred_lt.h"
39 #include "spstproc.h"
40 #include "cbsearch.h"
41 #include "gain_q.h"
42 #include "convolve.h"
43 #include "ton_stab.h"
44 #include "vad.h"
45 #include "dtx_enc.h"
46
47 /*
48 *****************************************************************************
49 * LOCAL VARIABLES AND TABLES
50 *****************************************************************************
51 */
52
53 /*
54 *****************************************************************************
55 * PUBLIC VARIABLES AND TABLES
56 *****************************************************************************
57 */
58 /* Spectral expansion factors */
59
60 static const Word16 gamma1[M] =
61 {
62 30802, 28954, 27217, 25584, 24049,
63 22606, 21250, 19975, 18777, 17650
64 };
65
66 /* gamma1 differs for the 12k2 coder */
67 static const Word16 gamma1_12k2[M] =
68 {
69 29491, 26542, 23888, 21499, 19349,
70 17414, 15672, 14105, 12694, 11425
71 };
72
73 static const Word16 gamma2[M] =
74 {
75 19661, 11797, 7078, 4247, 2548,
76 1529, 917, 550, 330, 198
77 };
78
79 /*
80 *****************************************************************************
81 * PUBLIC PROGRAM CODE
82 *****************************************************************************
83 */
84
85 /*
86 **************************************************************************
87 *
88 * Function : cod_amr_reset
89 * Purpose : Resets state memory
90 *
91 **************************************************************************
92 */
93 void cod_amr_reset (cod_amrState *st, Flag dtx, Flag use_vad2)
94 {
95 Word16 i;
96
97 /* save DTX flag */
98 st->dtx = dtx;
99
100 /*-----------------------------------------------------------------------*
101 * Initialize pointers to speech vector. *
102 *-----------------------------------------------------------------------*/
103
104 st->new_speech = st->old_speech + L_TOTAL - L_FRAME; /* New speech */
105
106 st->speech = st->new_speech - L_NEXT; /* Present frame */
107
108 st->p_window = st->old_speech + L_TOTAL - L_WINDOW; /* For LPC window */
109 st->p_window_12k2 = st->p_window - L_NEXT; /* EFR LPC window: no lookahead */
110
111 /* Initialize static pointers */
112
113 st->wsp = st->old_wsp + PIT_MAX;
114 st->exc = st->old_exc + PIT_MAX + L_INTERPOL;
115 st->zero = st->ai_zero + MP1;
116 st->error = st->mem_err + M;
117 st->h1 = &st->hvec[L_SUBFR];
118
119 /* Static vectors to zero */
120
121 Set_zero(st->old_speech, L_TOTAL);
122 Set_zero(st->old_exc, PIT_MAX + L_INTERPOL);
123 Set_zero(st->old_wsp, PIT_MAX);
124 Set_zero(st->mem_syn, M);
125 Set_zero(st->mem_w, M);
126 Set_zero(st->mem_w0, M);
127 Set_zero(st->mem_err, M);
128 Set_zero(st->zero, L_SUBFR);
129 Set_zero(st->hvec, L_SUBFR); /* set to zero "h1[-L_SUBFR..-1]" */
130
131 /* OL LTP states */
132 for (i = 0; i < 5; i++)
133 {
134 st->old_lags[i] = 40;
135 }
136
137 /* Reset lpc states */
138 lpc_reset(&st->lpcSt);
139
140 /* Reset lsp states */
141 lsp_reset(&st->lspSt);
142
143 /* Reset clLtp states */
144 cl_ltp_reset(&st->clLtpSt);
145
146 gainQuant_reset(&st->gainQuantSt);
147
148 p_ol_wgh_reset(&st->pitchOLWghtSt);
149
150 ton_stab_reset(&st->tonStabSt);
151
152 vad_reset(&st->vadSt, use_vad2);
153
154 dtx_enc_reset(&st->dtx_encSt);
155
156 st->sharp = SHARPMIN;
157 }
158
159 /***************************************************************************
160 * FUNCTION: cod_amr_first
161 *
162 * PURPOSE: Copes with look-ahead.
163 *
164 * INPUTS:
165 * No input argument are passed to this function. However, before
166 * calling this function, 40 new speech data should be copied to the
167 * vector new_speech[]. This is a global pointer which is declared in
168 * this file (it points to the end of speech buffer minus 200).
169 *
170 ***************************************************************************/
171
172 int cod_amr_first(cod_amrState *st, /* i/o : State struct */
173 Word16 new_speech[]) /* i : speech input (L_FRAME) */
174 {
175 Copy(new_speech,&st->new_speech[-L_NEXT], L_NEXT);
176 /* Copy(new_speech,st->new_speech,L_FRAME); */
177
178 return 0;
179 }
180
181
182 /***************************************************************************
183 * FUNCTION: cod_amr
184 *
185 * PURPOSE: Main encoder routine.
186 *
187 * DESCRIPTION: This function is called every 20 ms speech frame,
188 * operating on the newly read 160 speech samples. It performs the
189 * principle encoding functions to produce the set of encoded parameters
190 * which include the LSP, adaptive codebook, and fixed codebook
191 * quantization indices (addresses and gains).
192 *
193 * INPUTS:
194 * No input argument are passed to this function. However, before
195 * calling this function, 160 new speech data should be copied to the
196 * vector new_speech[]. This is a global pointer which is declared in
197 * this file (it points to the end of speech buffer minus 160).
198 *
199 * OUTPUTS:
200 *
201 * ana[]: vector of analysis parameters.
202 * synth[]: Local synthesis speech (for debugging purposes)
203 *
204 ***************************************************************************/
205 int cod_amr(
206 cod_amrState *st, /* i/o : State struct */
207 enum Mode mode, /* i : AMR mode */
208 Word16 new_speech[], /* i : speech input (L_FRAME) */
209 Word16 ana[], /* o : Analysis parameters */
210 enum Mode *usedMode, /* o : used mode */
211 Word16 synth[] /* o : Local synthesis */
212 )
213 {
214 /* LPC coefficients */
215 Word16 A_t[(MP1) * 4]; /* A(z) unquantized for the 4 subframes */
216 Word16 Aq_t[(MP1) * 4]; /* A(z) quantized for the 4 subframes */
217 Word16 *A, *Aq; /* Pointer on A_t and Aq_t */
218 Word16 lsp_new[M];
219
220 /* Other vectors */
221 Word16 xn[L_SUBFR]; /* Target vector for pitch search */
222 Word16 xn2[L_SUBFR]; /* Target vector for codebook search */
223 Word16 code[L_SUBFR]; /* Fixed codebook excitation */
224 Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
225 Word16 y2[L_SUBFR]; /* Filtered fixed codebook excitation */
226 Word16 gCoeff[6]; /* Correlations between xn, y1, & y2: */
227 Word16 res[L_SUBFR]; /* Short term (LPC) prediction residual */
228 Word16 res2[L_SUBFR]; /* Long term (LTP) prediction residual */
229
230 /* Vector and scalars needed for the MR475 */
231 Word16 xn_sf0[L_SUBFR]; /* Target vector for pitch search */
232 Word16 y2_sf0[L_SUBFR]; /* Filtered codebook innovation */
233 Word16 code_sf0[L_SUBFR]; /* Fixed codebook excitation */
234 Word16 h1_sf0[L_SUBFR]; /* The impulse response of sf0 */
235 Word16 mem_syn_save[M]; /* Filter memory */
236 Word16 mem_w0_save[M]; /* Filter memory */
237 Word16 mem_err_save[M]; /* Filter memory */
238 Word16 sharp_save; /* Sharpening */
239 Word16 evenSubfr; /* Even subframe indicator */
240 Word16 T0_sf0 = 0; /* Integer pitch lag of sf0 */
241 Word16 T0_frac_sf0 = 0; /* Fractional pitch lag of sf0 */
242 Word16 i_subfr_sf0 = 0; /* Position in exc[] for sf0 */
243 Word16 gain_pit_sf0; /* Quantized pitch gain for sf0 */
244 Word16 gain_code_sf0; /* Quantized codebook gain for sf0 */
245
246 /* Scalars */
247 Word16 i_subfr, subfrNr;
248 Word16 T_op[L_FRAME/L_FRAME_BY2];
249 Word16 T0, T0_frac;
250 Word16 gain_pit, gain_code;
251
252 /* Flags */
253 Word16 lsp_flag = 0; /* indicates resonance in LPC filter */
254 Word16 gp_limit; /* pitch gain limit value */
255 Word16 vad_flag; /* VAD decision flag */
256 Word16 compute_sid_flag; /* SID analysis flag */
257
258 Copy(new_speech, st->new_speech, L_FRAME);
259
260 *usedMode = mode; move16 ();
261
262 /* DTX processing */
263 if (st->dtx)
264 { /* no test() call since this if is only in simulation env */
265 /* Find VAD decision */
266
267 if (st->vadSt.use_vad2) {
268 vad_flag = vad2(st->new_speech, &st->vadSt.u.v2);
269 vad_flag = vad2(st->new_speech+80, &st->vadSt.u.v2) || vad_flag;
270 } else {
271 vad_flag = vad1(&st->vadSt.u.v1, st->new_speech);
272 }
273
274 /* NB! usedMode may change here */
275 compute_sid_flag = tx_dtx_handler(&st->dtx_encSt,
276 vad_flag,
277 usedMode);
278 }
279 else
280 {
281 compute_sid_flag = 0; move16 ();
282 }
283
284 /*------------------------------------------------------------------------*
285 * - Perform LPC analysis: *
286 * * autocorrelation + lag windowing *
287 * * Levinson-durbin algorithm to find a[] *
288 * * convert a[] to lsp[] *
289 * * quantize and code the LSPs *
290 * * find the interpolated LSPs and convert to a[] for all *
291 * subframes (both quantized and unquantized) *
292 *------------------------------------------------------------------------*/
293
294 /* LP analysis */
295 lpc(&st->lpcSt, mode, st->p_window, st->p_window_12k2, A_t);
296
297 /* From A(z) to lsp. LSP quantization and interpolation */
298 lsp(&st->lspSt, mode, *usedMode, A_t, Aq_t, lsp_new, &ana);
299
300 /* Buffer lsp's and energy */
301 dtx_buffer(&st->dtx_encSt,
302 lsp_new,
303 st->new_speech);
304
305 /* Check if in DTX mode */
306 test();
307 if (sub(*usedMode, MRDTX) == 0)
308 {
309 dtx_enc(&st->dtx_encSt,
310 compute_sid_flag,
311 &st->lspSt.qSt,
312 &st->gainQuantSt.gc_predSt,
313 &ana);
314
315 Set_zero(st->old_exc, PIT_MAX + L_INTERPOL);
316 Set_zero(st->mem_w0, M);
317 Set_zero(st->mem_err, M);
318 Set_zero(st->zero, L_SUBFR);
319 Set_zero(st->hvec, L_SUBFR); /* set to zero "h1[-L_SUBFR..-1]" */
320 /* Reset lsp states */
321 lsp_reset(&st->lspSt);
322 Copy(lsp_new, st->lspSt.lsp_old, M);
323 Copy(lsp_new, st->lspSt.lsp_old_q, M);
324
325 /* Reset clLtp states */
326 cl_ltp_reset(&st->clLtpSt);
327 st->sharp = SHARPMIN;
328 }
329 else
330 {
331 /* check resonance in the filter */
332 lsp_flag = check_lsp(&st->tonStabSt, st->lspSt.lsp_old);
333 }
334
335 /*----------------------------------------------------------------------*
336 * - Find the weighted input speech w_sp[] for the whole speech frame *
337 * - Find the open-loop pitch delay for first 2 subframes *
338 * - Set the range for searching closed-loop pitch in 1st subframe *
339 * - Find the open-loop pitch delay for last 2 subframes *
340 *----------------------------------------------------------------------*/
341
342 if (st->dtx && st->vadSt.use_vad2)
343 { /* no test() call since this if is only in simulation env */
344 st->vadSt.u.v2.L_Rmax = 0;
345 st->vadSt.u.v2.L_R0 = 0;
346 }
347 for(subfrNr = 0, i_subfr = 0;
348 subfrNr < L_FRAME/L_FRAME_BY2;
349 subfrNr++, i_subfr += L_FRAME_BY2)
350 {
351 /* Pre-processing on 80 samples */
352 pre_big(mode, gamma1, gamma1_12k2, gamma2, A_t, i_subfr, st->speech,
353 st->mem_w, st->wsp);
354
355 test (); test ();
356 if ((sub(mode, MR475) != 0) && (sub(mode, MR515) != 0))
357 {
358 /* Find open loop pitch lag for two subframes */
359 ol_ltp(&st->pitchOLWghtSt, &st->vadSt, mode, &st->wsp[i_subfr],
360 &T_op[subfrNr], st->old_lags, st->ol_gain_flg, subfrNr,
361 st->dtx);
362 }
363 }
364
365 if ((sub(mode, MR475) == 0) || (sub(mode, MR515) == 0))
366 {
367 /* Find open loop pitch lag for ONE FRAME ONLY */
368 /* search on 160 samples */
369
370 ol_ltp(&st->pitchOLWghtSt, &st->vadSt, mode, &st->wsp[0], &T_op[0],
371 st->old_lags, st->ol_gain_flg, 1, st->dtx);
372 T_op[1] = T_op[0];
373 }
374
375 if (st->dtx && st->vadSt.use_vad2)
376 { /* no test() call since this if is only in simulation env */
377 LTP_flag_update(&st->vadSt.u.v2, mode);
378 }
379
380 /* run VAD pitch detection */
381 if (st->dtx && !st->vadSt.use_vad2)
382 { /* no test() call since this if is only in simulation env */
383 vad_pitch_detection(&st->vadSt.u.v1, T_op);
384 }
385
386 if (sub(*usedMode, MRDTX) == 0)
387 {
388 goto the_end;
389 }
390
391 /*------------------------------------------------------------------------*
392 * Loop for every subframe in the analysis frame *
393 *------------------------------------------------------------------------*
394 * To find the pitch and innovation parameters. The subframe size is *
395 * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. *
396 * - find the weighted LPC coefficients *
397 * - find the LPC residual signal res[] *
398 * - compute the target signal for pitch search *
399 * - compute impulse response of weighted synthesis filter (h1[]) *
400 * - find the closed-loop pitch parameters *
401 * - encode the pitch dealy *
402 * - update the impulse response h1[] by including fixed-gain pitch *
403 * - find target vector for codebook search *
404 * - codebook search *
405 * - encode codebook address *
406 * - VQ of pitch and codebook gains *
407 * - find synthesis speech *
408 * - update states of weighting filter *
409 *------------------------------------------------------------------------*/
410
411 A = A_t; /* pointer to interpolated LPC parameters */
412 Aq = Aq_t; /* pointer to interpolated quantized LPC parameters */
413
414 evenSubfr = 0; move16 ();
415 subfrNr = -1; move16 ();
416 for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
417 {
418 subfrNr = add(subfrNr, 1);
419 evenSubfr = sub(1, evenSubfr);
420
421 /* Save states for the MR475 mode */
422 test(); test();
423 if ((evenSubfr != 0) && (sub(*usedMode, MR475) == 0))
424 {
425 Copy(st->mem_syn, mem_syn_save, M);
426 Copy(st->mem_w0, mem_w0_save, M);
427 Copy(st->mem_err, mem_err_save, M);
428 sharp_save = st->sharp;
429 }
430
431 /*-----------------------------------------------------------------*
432 * - Preprocessing of subframe *
433 *-----------------------------------------------------------------*/
434 if (sub(*usedMode, MR475) != 0)
435 {
436 subframePreProc(*usedMode, gamma1, gamma1_12k2,
437 gamma2, A, Aq, &st->speech[i_subfr],
438 st->mem_err, st->mem_w0, st->zero,
439 st->ai_zero, &st->exc[i_subfr],
440 st->h1, xn, res, st->error);
441 }
442 else
443 { /* MR475 */
444 subframePreProc(*usedMode, gamma1, gamma1_12k2,
445 gamma2, A, Aq, &st->speech[i_subfr],
446 st->mem_err, mem_w0_save, st->zero,
447 st->ai_zero, &st->exc[i_subfr],
448 st->h1, xn, res, st->error);
449
450 /* save impulse response (modified in cbsearch) */
451 if (evenSubfr != 0)
452 {
453 Copy (st->h1, h1_sf0, L_SUBFR);
454 }
455 }
456
457 /* copy the LP residual (res2 is modified in the CL LTP search) */
458 Copy (res, res2, L_SUBFR);
459
460 /*-----------------------------------------------------------------*
461 * - Closed-loop LTP search *
462 *-----------------------------------------------------------------*/
463 cl_ltp(&st->clLtpSt, &st->tonStabSt, *usedMode, i_subfr, T_op, st->h1,
464 &st->exc[i_subfr], res2, xn, lsp_flag, xn2, y1,
465 &T0, &T0_frac, &gain_pit, gCoeff, &ana,
466 &gp_limit);
467
468 /* update LTP lag history */
469 if ((subfrNr == 0) && (st->ol_gain_flg[0] > 0))
470 {
471 st->old_lags[1] = T0;
472 }
473
474 if ((sub(subfrNr, 3) == 0) && (st->ol_gain_flg[1] > 0))
475 {
476 st->old_lags[0] = T0;
477 }
478
479 /*-----------------------------------------------------------------*
480 * - Inovative codebook search (find index and gain) *
481 *-----------------------------------------------------------------*/
482 cbsearch(xn2, st->h1, T0, st->sharp, gain_pit, res2,
483 code, y2, &ana, *usedMode, subfrNr);
484
485 /*------------------------------------------------------*
486 * - Quantization of gains. *
487 *------------------------------------------------------*/
488 gainQuant(&st->gainQuantSt, *usedMode, res, &st->exc[i_subfr], code,
489 xn, xn2, y1, y2, gCoeff, evenSubfr, gp_limit,
490 &gain_pit_sf0, &gain_code_sf0,
491 &gain_pit, &gain_code, &ana);
492
493 /* update gain history */
494 update_gp_clipping(&st->tonStabSt, gain_pit);
495
496 if (sub(*usedMode, MR475) != 0)
497 {
498 /* Subframe Post Porcessing */
499 subframePostProc(st->speech, *usedMode, i_subfr, gain_pit,
500 gain_code, Aq, synth, xn, code, y1, y2, st->mem_syn,
501 st->mem_err, st->mem_w0, st->exc, &st->sharp);
502 }
503 else
504 {
505 if (evenSubfr != 0)
506 {
507 i_subfr_sf0 = i_subfr; move16 ();
508 Copy(xn, xn_sf0, L_SUBFR);
509 Copy(y2, y2_sf0, L_SUBFR);
510 Copy(code, code_sf0, L_SUBFR);
511 T0_sf0 = T0; move16 ();
512 T0_frac_sf0 = T0_frac; move16 ();
513
514 /* Subframe Post Porcessing */
515 subframePostProc(st->speech, *usedMode, i_subfr, gain_pit,
516 gain_code, Aq, synth, xn, code, y1, y2,
517 mem_syn_save, st->mem_err, mem_w0_save,
518 st->exc, &st->sharp);
519 st->sharp = sharp_save; move16();
520 }
521 else
522 {
523 /* update both subframes for the MR475 */
524
525 /* Restore states for the MR475 mode */
526 Copy(mem_err_save, st->mem_err, M);
527
528 /* re-build excitation for sf 0 */
529 Pred_lt_3or6(&st->exc[i_subfr_sf0], T0_sf0, T0_frac_sf0,
530 L_SUBFR, 1);
531 Convolve(&st->exc[i_subfr_sf0], h1_sf0, y1, L_SUBFR);
532
533 Aq -= MP1;
534 subframePostProc(st->speech, *usedMode, i_subfr_sf0,
535 gain_pit_sf0, gain_code_sf0, Aq,
536 synth, xn_sf0, code_sf0, y1, y2_sf0,
537 st->mem_syn, st->mem_err, st->mem_w0, st->exc,
538 &sharp_save); /* overwrites sharp_save */
539 Aq += MP1;
540
541 /* re-run pre-processing to get xn right (needed by postproc) */
542 /* (this also reconstructs the unsharpened h1 for sf 1) */
543 subframePreProc(*usedMode, gamma1, gamma1_12k2,
544 gamma2, A, Aq, &st->speech[i_subfr],
545 st->mem_err, st->mem_w0, st->zero,
546 st->ai_zero, &st->exc[i_subfr],
547 st->h1, xn, res, st->error);
548
549 /* re-build excitation sf 1 (changed if lag < L_SUBFR) */
550 Pred_lt_3or6(&st->exc[i_subfr], T0, T0_frac, L_SUBFR, 1);
551 Convolve(&st->exc[i_subfr], st->h1, y1, L_SUBFR);
552
553 subframePostProc(st->speech, *usedMode, i_subfr, gain_pit,
554 gain_code, Aq, synth, xn, code, y1, y2,
555 st->mem_syn, st->mem_err, st->mem_w0,
556 st->exc, &st->sharp);
557 }
558 }
559
560 A += MP1; /* interpolated LPC parameters for next subframe */
561 Aq += MP1;
562 }
563
564 Copy(&st->old_exc[L_FRAME], &st->old_exc[0], PIT_MAX + L_INTERPOL);
565
566 the_end:
567
568 /*--------------------------------------------------*
569 * Update signal for next frame. *
570 *--------------------------------------------------*/
571 Copy(&st->old_wsp[L_FRAME], &st->old_wsp[0], PIT_MAX);
572
573 Copy(&st->old_speech[L_FRAME], &st->old_speech[0], L_TOTAL - L_FRAME);
574
575 return 0;
576 }