1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2011 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_DecodeResidual.c
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org******************************************************************/
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19d68cf3220461be83bc246811c3ba99c4e21d0f5ebjornv@webrtc.org#include <string.h>
20d68cf3220461be83bc246811c3ba99c4e21d0f5ebjornv@webrtc.org
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "defines.h"
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "state_construct.h"
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "cb_construct.h"
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "index_conv_dec.h"
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "do_plc.h"
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "constants.h"
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "enhancer_interface.h"
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "xcorr_coef.h"
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lsf_check.h"
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*----------------------------------------------------------------*
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  frame residual decoder function (subrutine to iLBC_decode)
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *---------------------------------------------------------------*/
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIlbcfix_DecodeResidual(
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    iLBC_Dec_Inst_t *iLBCdec_inst,
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* (i/o) the decoder state structure */
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits, which are used
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                for the decoding  */
40fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t *decresidual,  /* (o) decoded residual frame */
41fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t *syntdenum   /* (i) the decoded synthesis filter
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  coefficients */
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  ) {
44fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t meml_gotten, Nfor, Nback, diff, start_pos;
45fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t subcount, subframe;
46fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t *reverseDecresidual = iLBCdec_inst->enh_buf; /* Reversed decoded data, used for decoding backwards in time (reuse memory in state) */
47fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t *memVec = iLBCdec_inst->prevResidual;  /* Memory for codebook and filter state (reuse memory in state) */
48fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t *mem = &memVec[CB_HALFFILTERLEN];   /* Memory for codebook */
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  diff = STATE_LEN - iLBCdec_inst->state_short_len;
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (iLBC_encbits->state_first == 1) {
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    start_pos = (iLBC_encbits->startIdx-1)*SUBL;
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    start_pos = (iLBC_encbits->startIdx-1)*SUBL + diff;
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* decode scalar part of start state */
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIlbcfix_StateConstruct(iLBC_encbits->idxForMax,
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               iLBC_encbits->idxVec, &syntdenum[(iLBC_encbits->startIdx-1)*(LPC_FILTERORDER+1)],
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               &decresidual[start_pos], iLBCdec_inst->state_short_len
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               );
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (iLBC_encbits->state_first) { /* put adaptive part in the end */
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* setup memory */
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
69fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    WebRtcSpl_MemSetW16(mem, 0, (int16_t)(CB_MEML-iLBCdec_inst->state_short_len));
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCdec_inst->state_short_len, decresidual+start_pos,
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          iLBCdec_inst->state_short_len);
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* construct decoded vector */
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIlbcfix_CbConstruct(
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        &decresidual[start_pos+iLBCdec_inst->state_short_len],
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        iLBC_encbits->cb_index, iLBC_encbits->gain_index,
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mem+CB_MEML-ST_MEM_L_TBL,
79fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org        ST_MEM_L_TBL, (int16_t)diff
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              );
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  else {/* put adaptive part in the beginning */
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* setup memory */
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    meml_gotten = iLBCdec_inst->state_short_len;
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1,
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  decresidual+start_pos, meml_gotten);
90fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    WebRtcSpl_MemSetW16(mem, 0, (int16_t)(CB_MEML-meml_gotten));
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* construct decoded vector */
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIlbcfix_CbConstruct(
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        reverseDecresidual,
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        iLBC_encbits->cb_index, iLBC_encbits->gain_index,
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mem+CB_MEML-ST_MEM_L_TBL,
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ST_MEM_L_TBL, diff
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              );
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* get decoded residual from reversed vector */
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1],
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  reverseDecresidual, diff);
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* counter for predicted subframes */
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  subcount=1;
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* forward prediction of subframes */
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Nfor = iLBCdec_inst->nsub-iLBC_encbits->startIdx-1;
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if( Nfor > 0 ) {
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* setup memory */
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN);
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN,
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          decresidual+(iLBC_encbits->startIdx-1)*SUBL, STATE_LEN);
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* loop over subframes to encode */
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (subframe=0; subframe<Nfor; subframe++) {
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* construct decoded vector */
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIlbcfix_CbConstruct(
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &decresidual[(iLBC_encbits->startIdx+1+subframe)*SUBL],
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          iLBC_encbits->cb_index+subcount*CB_NSTAGES,
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          iLBC_encbits->gain_index+subcount*CB_NSTAGES,
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          mem, MEM_LF_TBL, SUBL
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                );
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* update memory */
135d68cf3220461be83bc246811c3ba99c4e21d0f5ebjornv@webrtc.org      memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            &decresidual[(iLBC_encbits->startIdx+1+subframe)*SUBL], SUBL);
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      subcount++;
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* backward prediction of subframes */
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Nback = iLBC_encbits->startIdx-1;
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if( Nback > 0 ){
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* setup memory */
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    meml_gotten = SUBL*(iLBCdec_inst->nsub+1-iLBC_encbits->startIdx);
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if( meml_gotten > CB_MEML ) {
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      meml_gotten=CB_MEML;
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1,
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  decresidual+(iLBC_encbits->startIdx-1)*SUBL, meml_gotten);
159fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    WebRtcSpl_MemSetW16(mem, 0, (int16_t)(CB_MEML-meml_gotten));
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* loop over subframes to decode */
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (subframe=0; subframe<Nback; subframe++) {
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* construct decoded vector */
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIlbcfix_CbConstruct(
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &reverseDecresidual[subframe*SUBL],
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          iLBC_encbits->cb_index+subcount*CB_NSTAGES,
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          iLBC_encbits->gain_index+subcount*CB_NSTAGES,
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          mem, MEM_LF_TBL, SUBL
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                );
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* update memory */
174d68cf3220461be83bc246811c3ba99c4e21d0f5ebjornv@webrtc.org      memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            &reverseDecresidual[subframe*SUBL], SUBL);
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      subcount++;
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* get decoded residual from reversed vector */
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcSpl_MemCpyReversedOrder(decresidual+SUBL*Nback-1,
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  reverseDecresidual, SUBL*Nback);
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
186