1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/******************************************************************
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org iLBC Speech Coder ANSI-C Source Code
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcIlbcfix_Decode.c
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org******************************************************************/
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "defines.h"
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "simple_lsf_dequant.h"
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "decoder_interpolate_lsf.h"
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "index_conv_dec.h"
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "do_plc.h"
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "constants.h"
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "enhancer_interface.h"
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "xcorr_coef.h"
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lsf_check.h"
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "decode_residual.h"
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "unpack_bits.h"
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "hp_output.h"
31d7e904161d5c59c61cbf094b16bca6e79ada713aandrew@webrtc.org#ifndef WEBRTC_ARCH_BIG_ENDIAN
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "swap_bytes.h"
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*----------------------------------------------------------------*
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  main decoder function
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *---------------------------------------------------------------*/
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIlbcfix_DecodeImpl(
40fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t *decblock,    /* (o) decoded signal block */
41fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    const uint16_t *bytes, /* (i) encoded signal bits */
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) the decoder state
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                           structure */
44fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t mode      /* (i) 0: bad packet, PLC,
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                                   1: normal */
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           ) {
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int i;
48fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t order_plus_one;
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
50fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t last_bit;
51fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t *data;
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Stack based */
53fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t decresidual[BLOCKL_MAX];
54fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t PLCresidual[BLOCKL_MAX + LPC_FILTERORDER];
55fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t syntdenum[NSUB_MAX*(LPC_FILTERORDER+1)];
56fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t PLClpc[LPC_FILTERORDER + 1];
57d7e904161d5c59c61cbf094b16bca6e79ada713aandrew@webrtc.org#ifndef WEBRTC_ARCH_BIG_ENDIAN
58fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint16_t swapped[NO_OF_WORDS_30MS];
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  iLBC_bits *iLBCbits_inst = (iLBC_bits*)PLCresidual;
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Reuse some buffers that are non overlapping in order to save stack memory */
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  data = &PLCresidual[LPC_FILTERORDER];
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (mode) { /* the data are good */
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* decode data */
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Unpacketize bits into parameters */
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
71d7e904161d5c59c61cbf094b16bca6e79ada713aandrew@webrtc.org#ifndef WEBRTC_ARCH_BIG_ENDIAN
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIlbcfix_SwapBytes(bytes, iLBCdec_inst->no_of_words, swapped);
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    last_bit = WebRtcIlbcfix_UnpackBits(swapped, iLBCbits_inst, iLBCdec_inst->mode);
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#else
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    last_bit = WebRtcIlbcfix_UnpackBits(bytes, iLBCbits_inst, iLBCdec_inst->mode);
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Check for bit errors */
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (iLBCbits_inst->startIdx<1)
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      mode = 0;
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((iLBCdec_inst->mode==20) && (iLBCbits_inst->startIdx>3))
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      mode = 0;
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((iLBCdec_inst->mode==30) && (iLBCbits_inst->startIdx>5))
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      mode = 0;
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (last_bit==1)
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      mode = 0;
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (mode) { /* No bit errors was detected, continue decoding */
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Stack based */
90fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      int16_t lsfdeq[LPC_FILTERORDER*LPC_N_MAX];
91fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      int16_t weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* adjust index */
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIlbcfix_IndexConvDec(iLBCbits_inst->cb_index);
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* decode the lsf */
97fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      WebRtcIlbcfix_SimpleLsfDeQ(lsfdeq, (int16_t*)(iLBCbits_inst->lsf), iLBCdec_inst->lpc_n);
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIlbcfix_LsfCheck(lsfdeq, LPC_FILTERORDER, iLBCdec_inst->lpc_n);
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIlbcfix_DecoderInterpolateLsp(syntdenum, weightdenum,
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          lsfdeq, LPC_FILTERORDER, iLBCdec_inst);
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Decode the residual using the cb and gain indexes */
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIlbcfix_DecodeResidual(iLBCdec_inst, iLBCbits_inst, decresidual, syntdenum);
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* preparing the plc for a future loss! */
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIlbcfix_DoThePlc( PLCresidual, PLClpc, 0,
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              decresidual, syntdenum + (LPC_FILTERORDER + 1)*(iLBCdec_inst->nsub - 1),
108fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                              (int16_t)(iLBCdec_inst->last_lag), iLBCdec_inst);
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Use the output from doThePLC */
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WEBRTC_SPL_MEMCPY_W16(decresidual, PLCresidual, iLBCdec_inst->blockl);
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (mode == 0) {
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* the data is bad (either a PLC call
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * was made or a bit error was detected)
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* packet loss conceal */
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIlbcfix_DoThePlc( PLCresidual, PLClpc, 1,
124fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            decresidual, syntdenum, (int16_t)(iLBCdec_inst->last_lag), iLBCdec_inst);
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_SPL_MEMCPY_W16(decresidual, PLCresidual, iLBCdec_inst->blockl);
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    order_plus_one = LPC_FILTERORDER + 1;
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (i = 0; i < iLBCdec_inst->nsub; i++) {
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WEBRTC_SPL_MEMCPY_W16(syntdenum+(i*order_plus_one),
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            PLClpc, order_plus_one);
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((*iLBCdec_inst).use_enhancer == 1) { /* Enhancer activated */
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Update the filter and filter coefficients if there was a packet loss */
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (iLBCdec_inst->prev_enh_pl==2) {
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (i=0;i<iLBCdec_inst->nsub;i++) {
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_SPL_MEMCPY_W16(&(iLBCdec_inst->old_syntdenum[i*(LPC_FILTERORDER+1)]),
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              syntdenum, (LPC_FILTERORDER+1));
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* post filtering */
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    (*iLBCdec_inst).last_lag =
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WebRtcIlbcfix_EnhancerInterface(data, decresidual, iLBCdec_inst);
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* synthesis filtering */
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Set up the filter state */
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_SPL_MEMCPY_W16(&data[-LPC_FILTERORDER], iLBCdec_inst->syntMem, LPC_FILTERORDER);
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (iLBCdec_inst->mode==20) {
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Enhancer has 40 samples delay */
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      i=0;
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcSpl_FilterARFastQ12(
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          data, data,
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          iLBCdec_inst->old_syntdenum + (i+iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1),
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          LPC_FILTERORDER+1, SUBL);
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (i=1; i < iLBCdec_inst->nsub; i++) {
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WebRtcSpl_FilterARFastQ12(
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            data+i*SUBL, data+i*SUBL,
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            syntdenum+(i-1)*(LPC_FILTERORDER+1),
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            LPC_FILTERORDER+1, SUBL);
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (iLBCdec_inst->mode==30) {
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Enhancer has 80 samples delay */
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (i=0; i < 2; i++) {
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WebRtcSpl_FilterARFastQ12(
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            data+i*SUBL, data+i*SUBL,
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            iLBCdec_inst->old_syntdenum + (i+4)*(LPC_FILTERORDER+1),
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            LPC_FILTERORDER+1, SUBL);
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (i=2; i < iLBCdec_inst->nsub; i++) {
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WebRtcSpl_FilterARFastQ12(
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            data+i*SUBL, data+i*SUBL,
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            syntdenum+(i-2)*(LPC_FILTERORDER+1),
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            LPC_FILTERORDER+1, SUBL);
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save the filter state */
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &data[iLBCdec_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else { /* Enhancer not activated */
190fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t lag;
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Find last lag (since the enhancer is not called to give this info) */
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lag = 20;
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (iLBCdec_inst->mode==20) {
195fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      lag = (int16_t)WebRtcIlbcfix_XcorrCoef(
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &decresidual[iLBCdec_inst->blockl-60],
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &decresidual[iLBCdec_inst->blockl-60-lag],
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          60,
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          80, lag, -1);
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
201fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      lag = (int16_t)WebRtcIlbcfix_XcorrCoef(
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &decresidual[iLBCdec_inst->blockl-ENH_BLOCKL],
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &decresidual[iLBCdec_inst->blockl-ENH_BLOCKL-lag],
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          ENH_BLOCKL,
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          100, lag, -1);
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Store lag (it is needed if next packet is lost) */
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    (*iLBCdec_inst).last_lag = (int)lag;
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* copy data and run synthesis filter */
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_SPL_MEMCPY_W16(data, decresidual, iLBCdec_inst->blockl);
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Set up the filter state */
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_SPL_MEMCPY_W16(&data[-LPC_FILTERORDER], iLBCdec_inst->syntMem, LPC_FILTERORDER);
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (i=0; i < iLBCdec_inst->nsub; i++) {
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcSpl_FilterARFastQ12(
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          data+i*SUBL, data+i*SUBL,
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          syntdenum + i*(LPC_FILTERORDER+1),
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          LPC_FILTERORDER+1, SUBL);
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save the filter state */
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &data[iLBCdec_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WEBRTC_SPL_MEMCPY_W16(decblock,data,iLBCdec_inst->blockl);
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* High pass filter the signal (with upscaling a factor 2 and saturation) */
231fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  WebRtcIlbcfix_HpOutput(decblock, (int16_t*)WebRtcIlbcfix_kHpOutCoefs,
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         iLBCdec_inst->blockl);
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->old_syntdenum,
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        syntdenum, iLBCdec_inst->nsub*(LPC_FILTERORDER+1));
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  iLBCdec_inst->prev_enh_pl=0;
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (mode==0) { /* PLC was used */
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    iLBCdec_inst->prev_enh_pl=1;
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
244