Home | History | Annotate | Download | only in ilbc
      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 
     13  iLBC Speech Coder ANSI-C Source Code
     14 
     15  WebRtcIlbcfix_DoThePlc.c
     16 
     17 ******************************************************************/
     18 
     19 #include "defines.h"
     20 #include "constants.h"
     21 #include "comp_corr.h"
     22 #include "bw_expand.h"
     23 
     24 /*----------------------------------------------------------------*
     25  *  Packet loss concealment routine. Conceals a residual signal
     26  *  and LP parameters. If no packet loss, update state.
     27  *---------------------------------------------------------------*/
     28 
     29 void WebRtcIlbcfix_DoThePlc(
     30     int16_t *PLCresidual,  /* (o) concealed residual */
     31     int16_t *PLClpc,    /* (o) concealed LP parameters */
     32     int16_t PLI,     /* (i) packet loss indicator
     33                                                            0 - no PL, 1 = PL */
     34     int16_t *decresidual,  /* (i) decoded residual */
     35     int16_t *lpc,    /* (i) decoded LPC (only used for no PL) */
     36     int16_t inlag,    /* (i) pitch lag */
     37     iLBC_Dec_Inst_t *iLBCdec_inst
     38     /* (i/o) decoder instance */
     39                             ){
     40   int16_t i, pick;
     41   int32_t cross, ener, cross_comp, ener_comp = 0;
     42   int32_t measure, maxMeasure, energy;
     43   int16_t max, crossSquareMax, crossSquare;
     44   int16_t j, lag, tmp1, tmp2, randlag;
     45   int16_t shift1, shift2, shift3, shiftMax;
     46   int16_t scale3;
     47   int16_t corrLen;
     48   int32_t tmpW32, tmp2W32;
     49   int16_t use_gain;
     50   int16_t tot_gain;
     51   int16_t max_perSquare;
     52   int16_t scale1, scale2;
     53   int16_t totscale;
     54   int32_t nom;
     55   int16_t denom;
     56   int16_t pitchfact;
     57   int16_t use_lag;
     58   int ind;
     59   int16_t randvec[BLOCKL_MAX];
     60 
     61   /* Packet Loss */
     62   if (PLI == 1) {
     63 
     64     (*iLBCdec_inst).consPLICount += 1;
     65 
     66     /* if previous frame not lost,
     67        determine pitch pred. gain */
     68 
     69     if (iLBCdec_inst->prevPLI != 1) {
     70 
     71       /* Maximum 60 samples are correlated, preserve as high accuracy
     72          as possible without getting overflow */
     73       max = WebRtcSpl_MaxAbsValueW16((*iLBCdec_inst).prevResidual, (int16_t)iLBCdec_inst->blockl);
     74       scale3 = (WebRtcSpl_GetSizeInBits(max)<<1) - 25;
     75       if (scale3 < 0) {
     76         scale3 = 0;
     77       }
     78 
     79       /* Store scale for use when interpolating between the
     80        * concealment and the received packet */
     81       iLBCdec_inst->prevScale = scale3;
     82 
     83       /* Search around the previous lag +/-3 to find the
     84          best pitch period */
     85       lag = inlag - 3;
     86 
     87       /* Guard against getting outside the frame */
     88       corrLen = WEBRTC_SPL_MIN(60, iLBCdec_inst->blockl-(inlag+3));
     89 
     90       WebRtcIlbcfix_CompCorr( &cross, &ener,
     91                               iLBCdec_inst->prevResidual, lag, iLBCdec_inst->blockl, corrLen, scale3);
     92 
     93       /* Normalize and store cross^2 and the number of shifts */
     94       shiftMax = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross))-15;
     95       crossSquareMax = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(WEBRTC_SPL_SHIFT_W32(cross, -shiftMax),
     96                                                                 WEBRTC_SPL_SHIFT_W32(cross, -shiftMax), 15);
     97 
     98       for (j=inlag-2;j<=inlag+3;j++) {
     99         WebRtcIlbcfix_CompCorr( &cross_comp, &ener_comp,
    100                                 iLBCdec_inst->prevResidual, j, iLBCdec_inst->blockl, corrLen, scale3);
    101 
    102         /* Use the criteria (corr*corr)/energy to compare if
    103            this lag is better or not. To avoid the division,
    104            do a cross multiplication */
    105         shift1 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross_comp))-15;
    106         crossSquare = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1),
    107                                                                WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1), 15);
    108 
    109         shift2 = WebRtcSpl_GetSizeInBits(ener)-15;
    110         measure = WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_SHIFT_W32(ener, -shift2),
    111                                        crossSquare);
    112 
    113         shift3 = WebRtcSpl_GetSizeInBits(ener_comp)-15;
    114         maxMeasure = WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_SHIFT_W32(ener_comp, -shift3),
    115                                           crossSquareMax);
    116 
    117         /* Calculate shift value, so that the two measures can
    118            be put in the same Q domain */
    119         if(((shiftMax<<1)+shift3) > ((shift1<<1)+shift2)) {
    120           tmp1 = WEBRTC_SPL_MIN(31, (shiftMax<<1)+shift3-(shift1<<1)-shift2);
    121           tmp2 = 0;
    122         } else {
    123           tmp1 = 0;
    124           tmp2 = WEBRTC_SPL_MIN(31, (shift1<<1)+shift2-(shiftMax<<1)-shift3);
    125         }
    126 
    127         if ((measure>>tmp1) > (maxMeasure>>tmp2)) {
    128           /* New lag is better => record lag, measure and domain */
    129           lag = j;
    130           crossSquareMax = crossSquare;
    131           cross = cross_comp;
    132           shiftMax = shift1;
    133           ener = ener_comp;
    134         }
    135       }
    136 
    137       /* Calculate the periodicity for the lag with the maximum correlation.
    138 
    139          Definition of the periodicity:
    140          abs(corr(vec1, vec2))/(sqrt(energy(vec1))*sqrt(energy(vec2)))
    141 
    142          Work in the Square domain to simplify the calculations
    143          max_perSquare is less than 1 (in Q15)
    144       */
    145       tmp2W32=WebRtcSpl_DotProductWithScale(&iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
    146                                             &iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
    147                                             corrLen, scale3);
    148 
    149       if ((tmp2W32>0)&&(ener_comp>0)) {
    150         /* norm energies to int16_t, compute the product of the energies and
    151            use the upper int16_t as the denominator */
    152 
    153         scale1=(int16_t)WebRtcSpl_NormW32(tmp2W32)-16;
    154         tmp1=(int16_t)WEBRTC_SPL_SHIFT_W32(tmp2W32, scale1);
    155 
    156         scale2=(int16_t)WebRtcSpl_NormW32(ener)-16;
    157         tmp2=(int16_t)WEBRTC_SPL_SHIFT_W32(ener, scale2);
    158         denom=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp1, tmp2, 16); /* denom in Q(scale1+scale2-16) */
    159 
    160         /* Square the cross correlation and norm it such that max_perSquare
    161            will be in Q15 after the division */
    162 
    163         totscale = scale1+scale2-1;
    164         tmp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, (totscale>>1));
    165         tmp2 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, totscale-(totscale>>1));
    166 
    167         nom = WEBRTC_SPL_MUL_16_16(tmp1, tmp2);
    168         max_perSquare = (int16_t)WebRtcSpl_DivW32W16(nom, denom);
    169 
    170       } else {
    171         max_perSquare = 0;
    172       }
    173     }
    174 
    175     /* previous frame lost, use recorded lag and gain */
    176 
    177     else {
    178       lag = iLBCdec_inst->prevLag;
    179       max_perSquare = iLBCdec_inst->perSquare;
    180     }
    181 
    182     /* Attenuate signal and scale down pitch pred gain if
    183        several frames lost consecutively */
    184 
    185     use_gain = 32767;   /* 1.0 in Q15 */
    186 
    187     if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>320) {
    188       use_gain = 29491;  /* 0.9 in Q15 */
    189     } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>640) {
    190       use_gain = 22938;  /* 0.7 in Q15 */
    191     } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>960) {
    192       use_gain = 16384;  /* 0.5 in Q15 */
    193     } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>1280) {
    194       use_gain = 0;   /* 0.0 in Q15 */
    195     }
    196 
    197     /* Compute mixing factor of picth repeatition and noise:
    198        for max_per>0.7 set periodicity to 1.0
    199        0.4<max_per<0.7 set periodicity to (maxper-0.4)/0.7-0.4)
    200        max_per<0.4 set periodicity to 0.0
    201     */
    202 
    203     if (max_perSquare>7868) { /* periodicity > 0.7  (0.7^4=0.2401 in Q15) */
    204       pitchfact = 32767;
    205     } else if (max_perSquare>839) { /* 0.4 < periodicity < 0.7 (0.4^4=0.0256 in Q15) */
    206       /* find best index and interpolate from that */
    207       ind = 5;
    208       while ((max_perSquare<WebRtcIlbcfix_kPlcPerSqr[ind])&&(ind>0)) {
    209         ind--;
    210       }
    211       /* pitch fact is approximated by first order */
    212       tmpW32 = (int32_t)WebRtcIlbcfix_kPlcPitchFact[ind] +
    213           WEBRTC_SPL_MUL_16_16_RSFT(WebRtcIlbcfix_kPlcPfSlope[ind], (max_perSquare-WebRtcIlbcfix_kPlcPerSqr[ind]), 11);
    214 
    215       pitchfact = (int16_t)WEBRTC_SPL_MIN(tmpW32, 32767); /* guard against overflow */
    216 
    217     } else { /* periodicity < 0.4 */
    218       pitchfact = 0;
    219     }
    220 
    221     /* avoid repetition of same pitch cycle (buzzyness) */
    222     use_lag = lag;
    223     if (lag<80) {
    224       use_lag = 2*lag;
    225     }
    226 
    227     /* compute concealed residual */
    228     energy = 0;
    229 
    230     for (i=0; i<iLBCdec_inst->blockl; i++) {
    231 
    232       /* noise component -  52 < randlagFIX < 117 */
    233       iLBCdec_inst->seed = (int16_t)(WEBRTC_SPL_MUL_16_16(iLBCdec_inst->seed, 31821)+(int32_t)13849);
    234       randlag = 53 + (int16_t)(iLBCdec_inst->seed & 63);
    235 
    236       pick = i - randlag;
    237 
    238       if (pick < 0) {
    239         randvec[i] = iLBCdec_inst->prevResidual[iLBCdec_inst->blockl+pick];
    240       } else {
    241         randvec[i] = iLBCdec_inst->prevResidual[pick];
    242       }
    243 
    244       /* pitch repeatition component */
    245       pick = i - use_lag;
    246 
    247       if (pick < 0) {
    248         PLCresidual[i] = iLBCdec_inst->prevResidual[iLBCdec_inst->blockl+pick];
    249       } else {
    250         PLCresidual[i] = PLCresidual[pick];
    251       }
    252 
    253       /* Attinuate total gain for each 10 ms */
    254       if (i<80) {
    255         tot_gain=use_gain;
    256       } else if (i<160) {
    257         tot_gain=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(31130, use_gain, 15); /* 0.95*use_gain */
    258       } else {
    259         tot_gain=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(29491, use_gain, 15); /* 0.9*use_gain */
    260       }
    261 
    262 
    263       /* mix noise and pitch repeatition */
    264 
    265       PLCresidual[i] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tot_gain,
    266                                                                 (int16_t)WEBRTC_SPL_RSHIFT_W32( (WEBRTC_SPL_MUL_16_16(pitchfact, PLCresidual[i]) +
    267                                                                                                        WEBRTC_SPL_MUL_16_16((32767-pitchfact), randvec[i]) + 16384),
    268                                                                                                       15),
    269                                                                 15);
    270 
    271       /* Shifting down the result one step extra to ensure that no overflow
    272          will occur */
    273       energy += WEBRTC_SPL_MUL_16_16_RSFT(PLCresidual[i],
    274                                           PLCresidual[i], (iLBCdec_inst->prevScale+1));
    275 
    276     }
    277 
    278     /* less than 30 dB, use only noise */
    279     if (energy < (WEBRTC_SPL_SHIFT_W32(((int32_t)iLBCdec_inst->blockl*900),-(iLBCdec_inst->prevScale+1)))) {
    280       energy = 0;
    281       for (i=0; i<iLBCdec_inst->blockl; i++) {
    282         PLCresidual[i] = randvec[i];
    283       }
    284     }
    285 
    286     /* use the old LPC */
    287     WEBRTC_SPL_MEMCPY_W16(PLClpc, (*iLBCdec_inst).prevLpc, LPC_FILTERORDER+1);
    288 
    289     /* Update state in case there are multiple frame losses */
    290     iLBCdec_inst->prevLag = lag;
    291     iLBCdec_inst->perSquare = max_perSquare;
    292   }
    293 
    294   /* no packet loss, copy input */
    295 
    296   else {
    297     WEBRTC_SPL_MEMCPY_W16(PLCresidual, decresidual, iLBCdec_inst->blockl);
    298     WEBRTC_SPL_MEMCPY_W16(PLClpc, lpc, (LPC_FILTERORDER+1));
    299     iLBCdec_inst->consPLICount = 0;
    300   }
    301 
    302   /* update state */
    303   iLBCdec_inst->prevPLI = PLI;
    304   WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevLpc, PLClpc, (LPC_FILTERORDER+1));
    305   WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevResidual, PLCresidual, iLBCdec_inst->blockl);
    306 
    307   return;
    308 }
    309