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#include "typedefs.h"
21#include "settings.h"
22
23#include "lpc_shape_swb12_tables.h"
24#include "lpc_shape_swb16_tables.h"
25#include "lpc_gain_swb_tables.h"
26
27#include <stdio.h>
28#include <string.h>
29#include <math.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 */
47WebRtc_Word16
48WebRtcIsac_RemoveLarMean(
49    double* lar,
50    WebRtc_Word16 bandwidth)
51{
52  WebRtc_Word16 coeffCntr;
53  WebRtc_Word16 vecCntr;
54  WebRtc_Word16 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 */
101WebRtc_Word16
102WebRtcIsac_DecorrelateIntraVec(
103    const double* data,
104    double*       out,
105    WebRtc_Word16 bandwidth)
106{
107  const double* ptrData;
108  const double* ptrRow;
109  WebRtc_Word16 rowCntr;
110  WebRtc_Word16 colCntr;
111  WebRtc_Word16 larVecCntr;
112  WebRtc_Word16 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 */
175WebRtc_Word16
176WebRtcIsac_DecorrelateInterVec(
177    const double* data,
178    double* out,
179    WebRtc_Word16 bandwidth)
180{
181  WebRtc_Word16 coeffCntr;
182  WebRtc_Word16 rowCntr;
183  WebRtc_Word16 colCntr;
184  const double* decorrMat;
185  WebRtc_Word16 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 */
244double
245WebRtcIsac_QuantizeUncorrLar(
246    double* data,
247    int* recIdx,
248    WebRtc_Word16 bandwidth)
249{
250  WebRtc_Word16 cntr;
251  WebRtc_Word32 idx;
252  WebRtc_Word16 interVecDim;
253  const double* leftRecPoint;
254  double quantizationStepSize;
255  const WebRtc_Word16* 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 = (WebRtc_Word32)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 */
314WebRtc_Word16
315WebRtcIsac_DequantizeLpcParam(
316    const int* idx,
317    double*    out,
318    WebRtc_Word16 bandwidth)
319{
320  WebRtc_Word16 cntr;
321  WebRtc_Word16 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 */
370WebRtc_Word16
371WebRtcIsac_CorrelateIntraVec(
372    const double* data,
373    double*       out,
374    WebRtc_Word16 bandwidth)
375{
376  WebRtc_Word16 vecCntr;
377  WebRtc_Word16 rowCntr;
378  WebRtc_Word16 colCntr;
379  WebRtc_Word16 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 */
433WebRtc_Word16
434WebRtcIsac_CorrelateInterVec(
435    const double* data,
436    double*       out,
437    WebRtc_Word16 bandwidth)
438{
439  WebRtc_Word16 coeffCntr;
440  WebRtc_Word16 rowCntr;
441  WebRtc_Word16 colCntr;
442  WebRtc_Word16 interVecDim;
443  double myVec[UB16_LPC_VEC_PER_FRAME];
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 */
498WebRtc_Word16
499WebRtcIsac_AddLarMean(
500    double* data,
501    WebRtc_Word16 bandwidth)
502{
503  WebRtc_Word16 coeffCntr;
504  WebRtc_Word16 vecCntr;
505  WebRtc_Word16 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 */
547WebRtc_Word16
548WebRtcIsac_ToLogDomainRemoveMean(
549    double* data)
550{
551  WebRtc_Word16 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 */
572WebRtc_Word16 WebRtcIsac_DecorrelateLPGain(
573    const double* data,
574    double* out)
575{
576  WebRtc_Word16 rowCntr;
577  WebRtc_Word16 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 */
603double WebRtcIsac_QuantizeLpcGain(
604    double* data,
605    int*    idx)
606{
607  WebRtc_Word16 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 */
641WebRtc_Word16 WebRtcIsac_DequantizeLpcGain(
642    const int* idx,
643    double*    out)
644{
645  WebRtc_Word16 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 */
667WebRtc_Word16 WebRtcIsac_CorrelateLpcGain(
668    const double* data,
669    double* out)
670{
671  WebRtc_Word16 rowCntr;
672  WebRtc_Word16 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 */
699WebRtc_Word16 WebRtcIsac_AddMeanToLinearDomain(
700    double* lpcGains)
701{
702  WebRtc_Word16 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