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