Home | History | Annotate | Download | only in source
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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  */
    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  */
    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  */
    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  */
    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  */
    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