1 /*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 /*
12 * code_LPC_UB.c
13 *
14 * This file contains definition of functions used to
15 * encode LPC parameters (Shape & gain) of the upper band.
16 *
17 */
18
19 #include <math.h>
20 #include <stdio.h>
21 #include <string.h>
22
23 #include "modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h"
24 #include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
25 #include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
26 #include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
27 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
28
29 /******************************************************************************
30 * WebRtcIsac_RemoveLarMean()
31 *
32 * Remove the means from LAR coefficients.
33 *
34 * Input:
35 * -lar : pointer to lar vectors. LAR vectors are
36 * concatenated.
37 * -bandwidth : indicates if the given LAR vectors belong
38 * to SWB-12kHz or SWB-16kHz.
39 *
40 * Output:
41 * -lar : pointer to mean-removed LAR:s.
42 *
43 *
44 */
45 int16_t
WebRtcIsac_RemoveLarMean(double * lar,int16_t bandwidth)46 WebRtcIsac_RemoveLarMean(
47 double* lar,
48 int16_t bandwidth)
49 {
50 int16_t coeffCntr;
51 int16_t vecCntr;
52 int16_t numVec;
53 const double* meanLAR;
54 switch(bandwidth)
55 {
56 case isac12kHz:
57 {
58 numVec = UB_LPC_VEC_PER_FRAME;
59 meanLAR = WebRtcIsac_kMeanLarUb12;
60 break;
61 }
62 case isac16kHz:
63 {
64 numVec = UB16_LPC_VEC_PER_FRAME;
65 meanLAR = WebRtcIsac_kMeanLarUb16;
66 break;
67 }
68 default:
69 return -1;
70 }
71
72 for(vecCntr = 0; vecCntr < numVec; vecCntr++)
73 {
74 for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
75 {
76 // REMOVE MEAN
77 *lar++ -= meanLAR[coeffCntr];
78 }
79 }
80 return 0;
81 }
82
83 /******************************************************************************
84 * WebRtcIsac_DecorrelateIntraVec()
85 *
86 * Remove the correlation amonge the components of LAR vectors. If LAR vectors
87 * of one frame are put in a matrix where each column is a LAR vector of a
88 * sub-frame, then this is equivalent to multiplying the LAR matrix with
89 * a decorrelting mtrix from left.
90 *
91 * Input:
92 * -inLar : pointer to mean-removed LAR vecrtors.
93 * -bandwidth : indicates if the given LAR vectors belong
94 * to SWB-12kHz or SWB-16kHz.
95 *
96 * Output:
97 * -out : decorrelated LAR vectors.
98 */
99 int16_t
WebRtcIsac_DecorrelateIntraVec(const double * data,double * out,int16_t bandwidth)100 WebRtcIsac_DecorrelateIntraVec(
101 const double* data,
102 double* out,
103 int16_t bandwidth)
104 {
105 const double* ptrData;
106 const double* ptrRow;
107 int16_t rowCntr;
108 int16_t colCntr;
109 int16_t larVecCntr;
110 int16_t numVec;
111 const double* decorrMat;
112 switch(bandwidth)
113 {
114 case isac12kHz:
115 {
116 decorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
117 numVec = UB_LPC_VEC_PER_FRAME;
118 break;
119 }
120 case isac16kHz:
121 {
122 decorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
123 numVec = UB16_LPC_VEC_PER_FRAME;
124 break;
125 }
126 default:
127 return -1;
128 }
129
130 //
131 // decorrMat * data
132 //
133 // data is assumed to contain 'numVec' of LAR
134 // vectors (mean removed) each of dimension 'UB_LPC_ORDER'
135 // concatenated one after the other.
136 //
137
138 ptrData = data;
139 for(larVecCntr = 0; larVecCntr < numVec; larVecCntr++)
140 {
141 for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
142 {
143 ptrRow = &decorrMat[rowCntr * UB_LPC_ORDER];
144 *out = 0;
145 for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
146 {
147 *out += ptrData[colCntr] * ptrRow[colCntr];
148 }
149 out++;
150 }
151 ptrData += UB_LPC_ORDER;
152 }
153 return 0;
154 }
155
156 /******************************************************************************
157 * WebRtcIsac_DecorrelateInterVec()
158 *
159 * Remover the correlation among mean-removed LAR vectors. If LAR vectors
160 * of one frame are put in a matrix where each column is a LAR vector of a
161 * sub-frame, then this is equivalent to multiplying the LAR matrix with
162 * a decorrelting mtrix from right.
163 *
164 * Input:
165 * -data : pointer to matrix of LAR vectors. The matrix
166 * is stored column-wise.
167 * -bandwidth : indicates if the given LAR vectors belong
168 * to SWB-12kHz or SWB-16kHz.
169 *
170 * Output:
171 * -out : decorrelated LAR vectors.
172 */
173 int16_t
WebRtcIsac_DecorrelateInterVec(const double * data,double * out,int16_t bandwidth)174 WebRtcIsac_DecorrelateInterVec(
175 const double* data,
176 double* out,
177 int16_t bandwidth)
178 {
179 int16_t coeffCntr;
180 int16_t rowCntr;
181 int16_t colCntr;
182 const double* decorrMat;
183 int16_t interVecDim;
184
185 switch(bandwidth)
186 {
187 case isac12kHz:
188 {
189 decorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
190 interVecDim = UB_LPC_VEC_PER_FRAME;
191 break;
192 }
193 case isac16kHz:
194 {
195 decorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
196 interVecDim = UB16_LPC_VEC_PER_FRAME;
197 break;
198 }
199 default:
200 return -1;
201 }
202
203 //
204 // data * decorrMat
205 //
206 // data is of size 'interVecDim' * 'UB_LPC_ORDER'
207 // That is 'interVecDim' of LAR vectors (mean removed)
208 // in columns each of dimension 'UB_LPC_ORDER'.
209 // matrix is stored column-wise.
210 //
211
212 for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
213 {
214 for(colCntr = 0; colCntr < interVecDim; colCntr++)
215 {
216 out[coeffCntr + colCntr * UB_LPC_ORDER] = 0;
217 for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
218 {
219 out[coeffCntr + colCntr * UB_LPC_ORDER] +=
220 data[coeffCntr + rowCntr * UB_LPC_ORDER] *
221 decorrMat[rowCntr * interVecDim + colCntr];
222 }
223 }
224 }
225 return 0;
226 }
227
228 /******************************************************************************
229 * WebRtcIsac_QuantizeUncorrLar()
230 *
231 * Quantize the uncorrelated parameters.
232 *
233 * Input:
234 * -data : uncorrelated LAR vectors.
235 * -bandwidth : indicates if the given LAR vectors belong
236 * to SWB-12kHz or SWB-16kHz.
237 *
238 * Output:
239 * -data : quantized version of the input.
240 * -idx : pointer to quantization indices.
241 */
242 double
WebRtcIsac_QuantizeUncorrLar(double * data,int * recIdx,int16_t bandwidth)243 WebRtcIsac_QuantizeUncorrLar(
244 double* data,
245 int* recIdx,
246 int16_t bandwidth)
247 {
248 int16_t cntr;
249 int32_t idx;
250 int16_t interVecDim;
251 const double* leftRecPoint;
252 double quantizationStepSize;
253 const int16_t* numQuantCell;
254 switch(bandwidth)
255 {
256 case isac12kHz:
257 {
258 leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
259 quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
260 numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb12;
261 interVecDim = UB_LPC_VEC_PER_FRAME;
262 break;
263 }
264 case isac16kHz:
265 {
266 leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
267 quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
268 numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb16;
269 interVecDim = UB16_LPC_VEC_PER_FRAME;
270 break;
271 }
272 default:
273 return -1;
274 }
275
276 //
277 // Quantize the parametrs.
278 //
279 for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
280 {
281 idx = (int32_t)floor((*data - leftRecPoint[cntr]) /
282 quantizationStepSize + 0.5);
283 if(idx < 0)
284 {
285 idx = 0;
286 }
287 else if(idx >= numQuantCell[cntr])
288 {
289 idx = numQuantCell[cntr] - 1;
290 }
291
292 *data++ = leftRecPoint[cntr] + idx * quantizationStepSize;
293 *recIdx++ = idx;
294 }
295 return 0;
296 }
297
298
299 /******************************************************************************
300 * WebRtcIsac_DequantizeLpcParam()
301 *
302 * Get the quantized value of uncorrelated LARs given the quantization indices.
303 *
304 * Input:
305 * -idx : pointer to quantiztion indices.
306 * -bandwidth : indicates if the given LAR vectors belong
307 * to SWB-12kHz or SWB-16kHz.
308 *
309 * Output:
310 * -out : pointer to quantized values.
311 */
312 int16_t
WebRtcIsac_DequantizeLpcParam(const int * idx,double * out,int16_t bandwidth)313 WebRtcIsac_DequantizeLpcParam(
314 const int* idx,
315 double* out,
316 int16_t bandwidth)
317 {
318 int16_t cntr;
319 int16_t interVecDim;
320 const double* leftRecPoint;
321 double quantizationStepSize;
322
323 switch(bandwidth)
324 {
325 case isac12kHz:
326 {
327 leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
328 quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
329 interVecDim = UB_LPC_VEC_PER_FRAME;
330 break;
331 }
332 case isac16kHz:
333 {
334 leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
335 quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
336 interVecDim = UB16_LPC_VEC_PER_FRAME;
337 break;
338 }
339 default:
340 return -1;
341 }
342
343 //
344 // Dequantize given the quantization indices
345 //
346
347 for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
348 {
349 *out++ = leftRecPoint[cntr] + *idx++ * quantizationStepSize;
350 }
351 return 0;
352 }
353
354
355 /******************************************************************************
356 * WebRtcIsac_CorrelateIntraVec()
357 *
358 * This is the inverse of WebRtcIsac_DecorrelateIntraVec().
359 *
360 * Input:
361 * -data : uncorrelated parameters.
362 * -bandwidth : indicates if the given LAR vectors belong
363 * to SWB-12kHz or SWB-16kHz.
364 *
365 * Output:
366 * -out : correlated parametrs.
367 */
368 int16_t
WebRtcIsac_CorrelateIntraVec(const double * data,double * out,int16_t bandwidth)369 WebRtcIsac_CorrelateIntraVec(
370 const double* data,
371 double* out,
372 int16_t bandwidth)
373 {
374 int16_t vecCntr;
375 int16_t rowCntr;
376 int16_t colCntr;
377 int16_t numVec;
378 const double* ptrData;
379 const double* intraVecDecorrMat;
380
381 switch(bandwidth)
382 {
383 case isac12kHz:
384 {
385 numVec = UB_LPC_VEC_PER_FRAME;
386 intraVecDecorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
387 break;
388 }
389 case isac16kHz:
390 {
391 numVec = UB16_LPC_VEC_PER_FRAME;
392 intraVecDecorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
393 break;
394 }
395 default:
396 return -1;
397 }
398
399
400 ptrData = data;
401 for(vecCntr = 0; vecCntr < numVec; vecCntr++)
402 {
403 for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
404 {
405 *out = 0;
406 for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
407 {
408 *out += ptrData[rowCntr] *
409 intraVecDecorrMat[rowCntr * UB_LPC_ORDER + colCntr];
410 }
411 out++;
412 }
413 ptrData += UB_LPC_ORDER;
414 }
415 return 0;
416 }
417
418 /******************************************************************************
419 * WebRtcIsac_CorrelateInterVec()
420 *
421 * This is the inverse of WebRtcIsac_DecorrelateInterVec().
422 *
423 * Input:
424 * -data
425 * -bandwidth : indicates if the given LAR vectors belong
426 * to SWB-12kHz or SWB-16kHz.
427 *
428 * Output:
429 * -out : correlated parametrs.
430 */
431 int16_t
WebRtcIsac_CorrelateInterVec(const double * data,double * out,int16_t bandwidth)432 WebRtcIsac_CorrelateInterVec(
433 const double* data,
434 double* out,
435 int16_t bandwidth)
436 {
437 int16_t coeffCntr;
438 int16_t rowCntr;
439 int16_t colCntr;
440 int16_t interVecDim;
441 double myVec[UB16_LPC_VEC_PER_FRAME] = {0.0};
442 const double* interVecDecorrMat;
443
444 switch(bandwidth)
445 {
446 case isac12kHz:
447 {
448 interVecDim = UB_LPC_VEC_PER_FRAME;
449 interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
450 break;
451 }
452 case isac16kHz:
453 {
454 interVecDim = UB16_LPC_VEC_PER_FRAME;
455 interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
456 break;
457 }
458 default:
459 return -1;
460 }
461
462 for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
463 {
464 for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
465 {
466 myVec[rowCntr] = 0;
467 for(colCntr = 0; colCntr < interVecDim; colCntr++)
468 {
469 myVec[rowCntr] += data[coeffCntr + colCntr * UB_LPC_ORDER] * //*ptrData *
470 interVecDecorrMat[rowCntr * interVecDim + colCntr];
471 //ptrData += UB_LPC_ORDER;
472 }
473 }
474
475 for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
476 {
477 out[coeffCntr + rowCntr * UB_LPC_ORDER] = myVec[rowCntr];
478 }
479 }
480 return 0;
481 }
482
483 /******************************************************************************
484 * WebRtcIsac_AddLarMean()
485 *
486 * This is the inverse of WebRtcIsac_RemoveLarMean()
487 *
488 * Input:
489 * -data : pointer to mean-removed LAR:s.
490 * -bandwidth : indicates if the given LAR vectors belong
491 * to SWB-12kHz or SWB-16kHz.
492 *
493 * Output:
494 * -data : pointer to LARs.
495 */
496 int16_t
WebRtcIsac_AddLarMean(double * data,int16_t bandwidth)497 WebRtcIsac_AddLarMean(
498 double* data,
499 int16_t bandwidth)
500 {
501 int16_t coeffCntr;
502 int16_t vecCntr;
503 int16_t numVec;
504 const double* meanLAR;
505
506 switch(bandwidth)
507 {
508 case isac12kHz:
509 {
510 numVec = UB_LPC_VEC_PER_FRAME;
511 meanLAR = WebRtcIsac_kMeanLarUb12;
512 break;
513 }
514 case isac16kHz:
515 {
516 numVec = UB16_LPC_VEC_PER_FRAME;
517 meanLAR = WebRtcIsac_kMeanLarUb16;
518 break;
519 }
520 default:
521 return -1;
522 }
523
524 for(vecCntr = 0; vecCntr < numVec; vecCntr++)
525 {
526 for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
527 {
528 *data++ += meanLAR[coeffCntr];
529 }
530 }
531 return 0;
532 }
533
534 /******************************************************************************
535 * WebRtcIsac_ToLogDomainRemoveMean()
536 *
537 * Transform the LPC gain to log domain then remove the mean value.
538 *
539 * Input:
540 * -lpcGain : pointer to LPC Gain, expecting 6 LPC gains
541 *
542 * Output:
543 * -lpcGain : mean-removed in log domain.
544 */
545 int16_t
WebRtcIsac_ToLogDomainRemoveMean(double * data)546 WebRtcIsac_ToLogDomainRemoveMean(
547 double* data)
548 {
549 int16_t coeffCntr;
550 for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
551 {
552 data[coeffCntr] = log(data[coeffCntr]) - WebRtcIsac_kMeanLpcGain;
553 }
554 return 0;
555 }
556
557
558 /******************************************************************************
559 * WebRtcIsac_DecorrelateLPGain()
560 *
561 * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
562 * multiplying gain vector with decorrelating matrix.
563 *
564 * Input:
565 * -data : LPC gain in log-domain with mean removed.
566 *
567 * Output:
568 * -out : decorrelated parameters.
569 */
WebRtcIsac_DecorrelateLPGain(const double * data,double * out)570 int16_t WebRtcIsac_DecorrelateLPGain(
571 const double* data,
572 double* out)
573 {
574 int16_t rowCntr;
575 int16_t colCntr;
576
577 for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
578 {
579 *out = 0;
580 for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
581 {
582 *out += data[rowCntr] * WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr];
583 }
584 out++;
585 }
586 return 0;
587 }
588
589 /******************************************************************************
590 * WebRtcIsac_QuantizeLpcGain()
591 *
592 * Quantize the decorrelated log-domain gains.
593 *
594 * Input:
595 * -lpcGain : uncorrelated LPC gains.
596 *
597 * Output:
598 * -idx : quantization indices
599 * -lpcGain : quantized value of the inpt.
600 */
WebRtcIsac_QuantizeLpcGain(double * data,int * idx)601 double WebRtcIsac_QuantizeLpcGain(
602 double* data,
603 int* idx)
604 {
605 int16_t coeffCntr;
606 for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
607 {
608 *idx = (int)floor((*data - WebRtcIsac_kLeftRecPointLpcGain[coeffCntr]) /
609 WebRtcIsac_kQSizeLpcGain + 0.5);
610
611 if(*idx < 0)
612 {
613 *idx = 0;
614 }
615 else if(*idx >= WebRtcIsac_kNumQCellLpcGain[coeffCntr])
616 {
617 *idx = WebRtcIsac_kNumQCellLpcGain[coeffCntr] - 1;
618 }
619 *data = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
620 WebRtcIsac_kQSizeLpcGain;
621
622 data++;
623 idx++;
624 }
625 return 0;
626 }
627
628 /******************************************************************************
629 * WebRtcIsac_DequantizeLpcGain()
630 *
631 * Get the quantized values given the quantization indices.
632 *
633 * Input:
634 * -idx : pointer to quantization indices.
635 *
636 * Output:
637 * -lpcGains : quantized values of the given parametes.
638 */
WebRtcIsac_DequantizeLpcGain(const int * idx,double * out)639 int16_t WebRtcIsac_DequantizeLpcGain(
640 const int* idx,
641 double* out)
642 {
643 int16_t coeffCntr;
644 for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
645 {
646 *out = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
647 WebRtcIsac_kQSizeLpcGain;
648 out++;
649 idx++;
650 }
651 return 0;
652 }
653
654 /******************************************************************************
655 * WebRtcIsac_CorrelateLpcGain()
656 *
657 * This is the inverse of WebRtcIsac_DecorrelateLPGain().
658 *
659 * Input:
660 * -data : decorrelated parameters.
661 *
662 * Output:
663 * -out : correlated parameters.
664 */
WebRtcIsac_CorrelateLpcGain(const double * data,double * out)665 int16_t WebRtcIsac_CorrelateLpcGain(
666 const double* data,
667 double* out)
668 {
669 int16_t rowCntr;
670 int16_t colCntr;
671
672 for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
673 {
674 *out = 0;
675 for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
676 {
677 *out += WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr] * data[colCntr];
678 }
679 out++;
680 }
681
682 return 0;
683 }
684
685
686 /******************************************************************************
687 * WebRtcIsac_AddMeanToLinearDomain()
688 *
689 * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
690 *
691 * Input:
692 * -lpcGain : LPC gain in log-domain & mean removed
693 *
694 * Output:
695 * -lpcGain : LPC gain in normal domain.
696 */
WebRtcIsac_AddMeanToLinearDomain(double * lpcGains)697 int16_t WebRtcIsac_AddMeanToLinearDomain(
698 double* lpcGains)
699 {
700 int16_t coeffCntr;
701 for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
702 {
703 lpcGains[coeffCntr] = exp(lpcGains[coeffCntr] + WebRtcIsac_kMeanLpcGain);
704 }
705 return 0;
706 }
707