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