comparison libgsmhr1/dtx_enc.c @ 613:7ce83c70ec5f

libgsmhr1: integrate encoder DTX functions, first round
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 05 Mar 2026 07:53:49 +0000
parents
children e6e9d5104503
comparison
equal deleted inserted replaced
612:a5879e04ad47 613:7ce83c70ec5f
1 /***************************************************************************
2 *
3 * File Name: dtx_enc.c
4 *
5 * Derivation: this module is the subset of GSM 06.06 dtx.c
6 * reduced to those functions that are used only by the speech
7 * encoder.
8 *
9 **************************************************************************/
10
11 /*________________________________________________________________________
12 | |
13 | Include Files |
14 |________________________________________________________________________|
15 */
16
17 #include "typedefs.h"
18 #include "namespace.h"
19 #include "mathhalf.h"
20 #include "mathdp31.h"
21 #include "enc_state.h"
22 #include "dtx_const.h"
23 #include "dtx_enc.h"
24 #include "dtx_rxfe.h"
25
26 /*________________________________________________________________________
27 | |
28 | Defines |
29 |________________________________________________________________________|
30 */
31
32 #define OH_SHIFT 3 /* shift corresponding to OVERHANG */
33
34 #define NP_AFLAT 4
35 #define LPC_VQ_SEG 3
36
37
38 /*************************************************************************
39 *
40 * FUNCTION NAME: swComfortNoise
41 *
42 * PURPOSE:
43 *
44 * This routine perform the following tasks:
45 * - generation of the speech flag (swSP)
46 * - averaging and encoding of the comfort noise parameters
47 * - randomization of the codebook indices
48 *
49 *
50 * INPUTS:
51 *
52 * swVadFrmCnt (global) - swVadFlag=0 frame counter.
53 * If swVadFlag=1 then this counter is 0, the first frame with
54 * swVadFlag=0 will set this counter to 1, with each additional
55 * swVadFlag=0 frame the counter is incremented.
56 *
57 * swVadFlag - voise activity flag. swVadFlag=0 frame with
58 * no voice activity, swVadFlag=0 frame with voice activity
59 *
60 * L_UnqntzdR0 - unquantized R(0), 32 bit value, output of
61 * FLAT.
62 *
63 * pL_UnqntzdCorr[NP+1] - unquantized correlation sequence,
64 * also an output of FLAT.
65 *
66 *
67 * OUTPUTS:
68 *
69 * swCNR0 - global variable, the output quantized R0 index
70 *
71 * pswCNLpc[3] - global variable, the output quantized LPC to the
72 * transmitted in the SID frame
73 *
74 * pswCNGsp0Code[N_SUB] - global variable, the output quantized GSP0 indices
75 *
76 * pswCNVSCode1[N_SUB] - global variable, the output quantized codevector 1
77 * indices.
78 *
79 * pswCNVSCode2[N_SUB] - global variable, the output quantized codevector 2
80 * indices.
81 *
82 *
83 * RETURN VALUE:
84 *
85 * swSP - speech flag, swSP=1 speech frames are generated, swSP=0
86 * SID frames are generated.
87 *
88 *************************************************************************/
89
90 Shortword swComfortNoise(struct gsmhr_encoder_state *st, Shortword swVadFlag,
91 Longword L_UnqntzdR0, Longword *pL_UnqntzdCorr)
92 {
93
94 /*_________________________________________________________________________
95 | |
96 | Automatic Variables |
97 |_________________________________________________________________________|
98 */
99
100 struct cn_state *cn_st = &st->cn_state;
101 Shortword swSP;
102 Shortword pswFinalRc[NP];
103
104 /* unquantized reference parameters */
105 Longword L_RefR0;
106 Longword pL_RefCorr[NP + 1];
107 Longword L_RefGs;
108
109 int i;
110
111
112 /*_________________________________________________________________________
113 | |
114 | Executable Code |
115 |_________________________________________________________________________|
116 */
117
118 swSP = 1;
119
120 /* VadFrmCnt will indicate the number of sequential frames where */
121 /* swVadFlag == 0 */
122 /* ------------------------------------------------------------- */
123
124 if (swVadFlag)
125 st->swVadFrmCnt = 0; /* Voice acitvity present */
126 else
127 st->swVadFrmCnt = add(st->swVadFrmCnt, 1); /* no voice activity */
128
129
130 /* swNElapsed will indicate the number of frames that have elapsed */
131 /* since the last SID frame with updated comfort noise parameters */
132 /* was generated */
133 /* --------------------------------------------------------------- */
134
135 st->swNElapsed = add(st->swNElapsed, 1);
136
137
138 /* If no voice activity was detected. */
139 /* ----------------------------------- */
140
141 if (st->swVadFrmCnt)
142 {
143
144 /* Short speech burst ? */
145 /* -------------------- */
146
147 if (st->swVadFrmCnt == 1)
148 {
149 if (sub(st->swNElapsed, 24) < 0)
150 cn_st->swShortBurst = 1; /* short speech burst detected */
151 else
152 cn_st->swShortBurst = 0; /* long speech burst detected */
153 }
154
155
156 /* Update history, with this frames data */
157 /* ------------------------------------- */
158
159 updateCNHist(st, L_UnqntzdR0, pL_UnqntzdCorr,
160 cn_st->pL_R0Hist, cn_st->ppL_CorrHist);
161
162
163 /* first SID frame */
164 /* --------------- */
165
166 if (((cn_st->swShortBurst == 0) && (st->swVadFrmCnt == OVERHANG)) ||
167 ((cn_st->swShortBurst == 1) && (st->swVadFrmCnt == 1)))
168 {
169
170 /* init. random generator */
171 /* ---------------------- */
172 cn_st->L_TxPNSeed = PN_INIT_SEED;
173
174
175 /* average GS */
176 /* ---------- */
177 avgGsHistQntz(st->pL_GsHist, &L_RefGs);
178
179
180 /* GS quantization */
181 /* --------------- */
182 cn_st->swRefGsIndex = gsQuant(L_RefGs, 0);
183
184 }
185
186
187 /* No Overhang in case of short speech bursts, */
188 /* generate SID frames with repeated comfort noise parameters */
189 /* ---------------------------------------------------------- */
190
191 if ((cn_st->swShortBurst == 1) && (st->swVadFrmCnt < OVERHANG))
192 {
193
194 /* generate a SID frame with repeated parameters */
195 /* --------------------------------------------- */
196
197 swSP = 0;
198
199
200 /* repeat data: r0, LPC, GS */
201 /* ------------------------ */
202
203 st->swCNR0 = cn_st->swQntRefR0;
204
205 for (i = 0; i < 3; i++)
206 st->pswCNLpc[i] = cn_st->piRefVqCodewds[i];
207
208 for (i = 0; i < N_SUB; i++)
209 st->pswCNGsp0Code[i] = cn_st->swRefGsIndex;
210
211 }
212
213
214 /* generate SID frames with updated comfort noise parameters */
215 /* --------------------------------------------------------- */
216
217 if (st->swVadFrmCnt >= OVERHANG)
218 {
219
220 /* A SID frame with updated parameters */
221 /* ----------------------------------- */
222
223 swSP = 0;
224 st->swNElapsed = 0;
225
226
227 /* average R0 and correlation values */
228 /* --------------------------------- */
229
230 avgCNHist(cn_st->pL_R0Hist, cn_st->ppL_CorrHist, &L_RefR0,
231 pL_RefCorr);
232
233
234 /* now quantize the averaged R(0) */
235 /* ------------------------------ */
236
237 cn_st->swQntRefR0 = r0Quant(L_RefR0);
238
239
240 /* Quantize the averaged correlation */
241 /* --------------------------------- */
242
243 lpcCorrQntz(pL_RefCorr,
244 pswFinalRc,
245 cn_st->piRefVqCodewds);
246
247
248 /* update frame data: r0, LPC */
249 /* -------------------------- */
250
251 st->swCNR0 = cn_st->swQntRefR0;
252 for (i = 0; i < 3; i++)
253 st->pswCNLpc[i] = cn_st->piRefVqCodewds[i];
254
255
256 /* update subframe data (unvoiced mode): GSP0 */
257 /* ------------------------------------------ */
258
259 for (i = 0; i < N_SUB; i++)
260 st->pswCNGsp0Code[i] = cn_st->swRefGsIndex;
261
262 }
263
264
265 /* random codevectors */
266 /* ------------------ */
267
268 if (swSP == 0)
269 {
270 for (i = 0; i < N_SUB; i++)
271 {
272 st->pswCNVSCode1[i] = getPnBits(7, &cn_st->L_TxPNSeed);
273 st->pswCNVSCode2[i] = getPnBits(7, &cn_st->L_TxPNSeed);
274 }
275 }
276
277
278 }
279
280 return (swSP);
281 }
282
283
284 /*************************************************************************
285 *
286 * FUNCTION NAME: updateCNHist
287 *
288 * PURPOSE:
289 *
290 * Add current frame's unquantized R(0) and LPC information to the
291 * comfort noise history, so that it will be available for
292 * averaging.
293 *
294 * INPUTS:
295 *
296 * Unquantized values from the coder:
297 *
298 *
299 * L_UnqntzdR0 - unquantized frame energy R(0), an output of FLAT
300 *
301 * pL_UnqntzdCorr[NP+1] - unquantized correlation coefficient
302 * array. Also an output of FLAT.
303 *
304 * siUpdPointer (global) - A modulo counter which counts up from
305 * 0 to OVERHANG-1.
306 *
307 * OUTPUTS:
308 *
309 * pL_R0History[OVERHANG] - history of the OVERHANG frames worth of
310 * R(0).
311 *
312 * ppL_CorrHistory[OVERHANG][NP+1] - - history of the OVERHANG
313 * frames worth of pL_UnqntzdCorr[].
314 *
315 * RETURN VALUE:
316 *
317 * none
318 *
319 *************************************************************************/
320
321 void updateCNHist(struct gsmhr_encoder_state *st, Longword L_UnqntzdR0,
322 Longword *pL_UnqntzdCorr, Longword pL_R0Hist[],
323 Longword ppL_CorrHist[OVERHANG][NP + 1])
324 {
325
326 /*_________________________________________________________________________
327 | |
328 | Automatic Variables |
329 |_________________________________________________________________________|
330 */
331
332 int i;
333
334
335 /*_________________________________________________________________________
336 | |
337 | Executable Code |
338 |_________________________________________________________________________|
339 */
340
341 /* update */
342 pL_R0Hist[st->siUpdPointer] = L_UnqntzdR0;
343
344 for (i = 0; i < NP + 1; i++)
345 ppL_CorrHist[st->siUpdPointer][i] = pL_UnqntzdCorr[i];
346
347 st->siUpdPointer = (st->siUpdPointer + 1) % OVERHANG;
348 }
349
350
351 /*************************************************************************
352 *
353 * FUNCTION NAME: avgCNHist
354 *
355 * PURPOSE:
356 *
357 * Average the unquantized R0 and LPC data stored at the encoder
358 * to arrive at an average R0 and LPC frame for use in a SID
359 * frame.
360 *
361 * INPUTS:
362 *
363 * pL_R0History[OVERHANG] - contains unquantized R(0) data from the
364 * most recent OVERHANG frame (including this one).
365 *
366 * ppL_CorrHistory[OVERHANG][NP+1] - Unquantized correlation
367 * coefficients from the most recent OVERHANG frame (including this
368 * one). The data stored here is an output of FLAT.
369 *
370 * OUTPUTS:
371 *
372 * *pL_AvgdR0 - the average of pL_R0History[]
373 *
374 * pL_AvgdCorrSeq[NP+1] - the average of ppL_CorrHistory[][].
375 *
376 *
377 * RETURN VALUE:
378 *
379 * none
380 *
381 *************************************************************************/
382
383 void avgCNHist(Longword pL_R0History[],
384 Longword ppL_CorrHistory[OVERHANG][NP + 1],
385 Longword *pL_AvgdR0, Longword pL_AvgdCorrSeq[])
386 {
387
388 /*_________________________________________________________________________
389 | |
390 | Automatic Variables |
391 |_________________________________________________________________________|
392 */
393
394 int i,
395 j;
396 Longword L_avg;
397
398 /*_________________________________________________________________________
399 | |
400 | Executable Code |
401 |_________________________________________________________________________|
402 */
403
404 /* R0 Averaging */
405 /* ------------ */
406
407 for (L_avg = 0, i = 0; i < OVERHANG; i++)
408 L_avg = L_add(L_shr(pL_R0History[i], OH_SHIFT), L_avg);
409
410 *pL_AvgdR0 = L_avg;
411
412
413 /* LPC: average the last OVERHANG frames */
414 /* ------------------------------------- */
415
416 for (j = 0; j < NP + 1; j++)
417 {
418 for (L_avg = 0, i = 0; i < OVERHANG; i++)
419 {
420 L_avg = L_add(L_shift_r(ppL_CorrHistory[i][j], -OH_SHIFT), L_avg);
421 }
422
423 pL_AvgdCorrSeq[j] = L_avg;
424 }
425
426 }
427
428
429 /***************************************************************************
430 *
431 * FUNCTION NAME: lpcCorrQntz
432 *
433 * PURPOSE: Quantize a correlation sequence
434 *
435 *
436 * INPUT:
437 *
438 * pL_CorrelSeq[NP+1]
439 * Correlation sequence to quantize.
440 *
441 * OUTPUTS:
442 *
443 * pswFinalRc[0:NP-1]
444 * A quantized set of NP reflection coefficients.
445 *
446 * piVQCodewds[0:2]
447 * An array containing the indices of the 3 reflection
448 * coefficient vectors selected from the three segment
449 * Rc-VQ.
450 *
451 * RETURN:
452 * None.
453 *
454 * KEYWORDS: AFLAT,aflat,flat,vectorquantization, reflectioncoefficients
455 *
456 *************************************************************************/
457
458 #if 0
459 void lpcCorrQntz(Longword pL_CorrelSeq[],
460 Shortword pswFinalRc[],
461 int piVQCodewds[])
462 {
463
464 /*_________________________________________________________________________
465 | |
466 | Automatic Variables |
467 |_________________________________________________________________________|
468 */
469
470 Shortword pswPOldSpace[NP_AFLAT],
471 pswPNewSpace[NP_AFLAT],
472 pswVOldSpace[2 * NP_AFLAT - 1],
473 pswVNewSpace[2 * NP_AFLAT - 1],
474 *ppswPAddrs[2],
475 *ppswVAddrs[2],
476 *pswVBar,
477 pswPBar[NP_AFLAT],
478 pswVBarSpace[2 * NP_AFLAT - 1],
479 pswFlatsRc[NP], /* Unquantized Rc's computed by FLAT */
480 pswRc[NP + 1]; /* Temp list for the converted RC's */
481 Longword *pL_VBarFull,
482 pL_PBarFull[NP],
483 pL_VBarFullSpace[2 * NP - 1];
484
485 int i,
486 iVec,
487 iSeg,
488 iCnt; /* Loop counter */
489 struct QuantList quantList, /* A list of vectors */
490 bestPql[4]; /* The four best vectors from
491 * the PreQ */
492 struct QuantList bestQl[LPC_VQ_SEG + 1]; /* Best vectors for each of
493 * the three segments */
494
495 /*_________________________________________________________________________
496 | |
497 | Executable Code |
498 |_________________________________________________________________________|
499 */
500
501 /* Setup pointers temporary space */
502 /*--------------------------------*/
503
504 pswVBar = pswVBarSpace + NP_AFLAT - 1;
505 pL_VBarFull = pL_VBarFullSpace + NP - 1;
506 ppswPAddrs[0] = pswPOldSpace;
507 ppswPAddrs[1] = pswPNewSpace;
508 ppswVAddrs[0] = pswVOldSpace + NP_AFLAT - 1;
509 ppswVAddrs[1] = pswVNewSpace + NP_AFLAT - 1;
510
511
512 /* Set up pL_PBarFull and pL_VBarFull initial conditions, using the */
513 /* autocorrelation sequence derived from the optimal reflection */
514 /* coefficients computed by FLAT. The initial conditions are shifted */
515 /* right by RSHIFT bits. These initial conditions, stored as */
516 /* Longwords, are used to initialize PBar and VBar arrays for the */
517 /* next VQ segment. */
518 /*--------------------------------------------------------------------*/
519
520 initPBarFullVBarFullL(pL_CorrelSeq, pL_PBarFull, pL_VBarFull);
521
522 /* Set up initial PBar and VBar initial conditions, using pL_PBarFull */
523 /* and pL_VBarFull arrays initialized above. These are the initial */
524 /* PBar and VBar conditions to be used by the AFLAT recursion at the */
525 /* 1-st Rc-VQ segment. */
526 /*--------------------------------------------------------------------*/
527
528 initPBarVBarL(pL_PBarFull, pswPBar, pswVBar);
529
530 for (iSeg = 1; iSeg <= LPC_VQ_SEG; iSeg++)
531 {
532 /* initialize candidate list */
533 /*---------------------------*/
534
535 quantList.iNum = psrPreQSz[iSeg - 1];
536 quantList.iRCIndex = 0;
537
538 /* do aflat for all vectors in the list */
539 /*--------------------------------------*/
540
541 setupPreQ(iSeg, quantList.iRCIndex); /* set up vector ptrs */
542
543 for (iCnt = 0; iCnt < quantList.iNum; iCnt++)
544 {
545 /* get a vector */
546 /*--------------*/
547
548 getNextVec(pswRc);
549
550 /* clear the limiter flag */
551 /*------------------------*/
552
553 iLimit = 0;
554
555 /* find the error values for each vector */
556 /*---------------------------------------*/
557
558 quantList.pswPredErr[iCnt] =
559 aflatRecursion(&pswRc[psvqIndex[iSeg - 1].l],
560 pswPBar, pswVBar,
561 ppswPAddrs, ppswVAddrs,
562 psvqIndex[iSeg - 1].len);
563
564 /* check the limiter flag */
565 /*------------------------*/
566
567 if (iLimit)
568 quantList.pswPredErr[iCnt] = 0x7fff; /* set error to bad value */
569
570 } /* done list loop */
571
572 /* find 4 best prequantizer levels */
573 /*---------------------------------*/
574
575 findBestInQuantList(quantList, 4, bestPql);
576
577 for (iVec = 0; iVec < 4; iVec++)
578 {
579
580 /* initialize quantizer list */
581 /*---------------------------*/
582
583 quantList.iNum = psrQuantSz[iSeg - 1];
584 quantList.iRCIndex = bestPql[iVec].iRCIndex * psrQuantSz[iSeg - 1];
585
586 setupQuant(iSeg, quantList.iRCIndex); /* set up vector ptrs */
587
588 /* do aflat recursion on each element of list */
589 /*--------------------------------------------*/
590
591 for (iCnt = 0; iCnt < quantList.iNum; iCnt++)
592 {
593 /* get a vector */
594 /*--------------*/
595
596 getNextVec(pswRc);
597
598 /* clear the limiter flag */
599 /*------------------------*/
600
601 iLimit = 0;
602
603 /* find the error values for each vector */
604 /*---------------------------------------*/
605
606 quantList.pswPredErr[iCnt] =
607 aflatRecursion(&pswRc[psvqIndex[iSeg - 1].l],
608 pswPBar, pswVBar,
609 ppswPAddrs, ppswVAddrs,
610 psvqIndex[iSeg - 1].len);
611
612 /* check the limiter flag */
613 /*------------------------*/
614
615 if (iLimit)
616 quantList.pswPredErr[iCnt] = 0x7fff; /* set error to the worst
617 * value */
618
619 } /* done list loop */
620
621 /* find best quantizer vector for this segment, and save it */
622 /*----------------------------------------------------------*/
623
624 findBestInQuantList(quantList, 1, bestQl);
625 if (iVec == 0)
626 bestQl[iSeg] = bestQl[0];
627 else if (sub(bestQl[iSeg].pswPredErr[0], bestQl[0].pswPredErr[0]) > 0)
628 bestQl[iSeg] = bestQl[0];
629
630 }
631
632 /* find the quantized reflection coefficients */
633 /*--------------------------------------------*/
634
635 setupQuant(iSeg, bestQl[iSeg].iRCIndex); /* set up vector ptrs */
636 getNextVec((Shortword *) (pswFinalRc - 1));
637
638
639 /* Update pBarFull and vBarFull for the next Rc-VQ segment, and */
640 /* update the pswPBar and pswVBar for the next Rc-VQ segment */
641 /*--------------------------------------------------------------*/
642
643 if (iSeg < LPC_VQ_SEG)
644 aflatNewBarRecursionL(&pswFinalRc[psvqIndex[iSeg - 1].l - 1], iSeg,
645 pL_PBarFull, pL_VBarFull, pswPBar, pswVBar);
646
647 }
648
649 /* find the quantizer index (the values to be output in the symbol file) */
650 /*-----------------------------------------------------------------*/
651
652 for (iSeg = 1; iSeg <= LPC_VQ_SEG; iSeg++)
653 piVQCodewds[iSeg - 1] = bestQl[iSeg].iRCIndex;
654
655 }
656 #endif