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