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 * decode.c
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * This C file contains the internal decoding function.
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string.h>
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "bandwidth_estimator.h"
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "codec.h"
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "entropy_coding.h"
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pitch_estimator.h"
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "settings.h"
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "structs.h"
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
30fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsacfix_DecodeImpl(int16_t       *signal_out16,
31fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                 ISACFIX_DecInst_t *ISACdec_obj,
32fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                 int16_t       *current_framesamples)
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
36fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t BWno;
37fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t len = 0;
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
39fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t model;
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
42fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t Vector_Word16_1[FRAMESAMPLES/2];
43fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t Vector_Word16_2[FRAMESAMPLES/2];
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
45fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t Vector_Word32_1[FRAMESAMPLES/2];
46fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t Vector_Word32_2[FRAMESAMPLES/2];
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
48fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
49fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
50fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t gain_lo_hiQ17[2*SUBFRAMES];
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
52fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t PitchLags_Q7[PITCH_SUBFRAMES];
53fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t PitchGains_Q12[PITCH_SUBFRAMES];
54fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t AvgPitchGain_Q12;
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
56fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t tmp_1, tmp_2;
57fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmp32a, tmp32b;
58fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t gainQ13;
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
61fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t frame_nb; /* counter */
62fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t frame_mode; /* 0 for 20ms and 30ms, 1 for 60ms */
63fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t processed_samples;
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* PLC */
66fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t overlapWin[ 240 ];
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  (ISACdec_obj->bitstr_obj).W_upper = 0xFFFFFFFF;
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  (ISACdec_obj->bitstr_obj).streamval = 0;
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  (ISACdec_obj->bitstr_obj).stream_index = 0;
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  (ISACdec_obj->bitstr_obj).full = 1;
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* decode framelength and BW estimation - not used, only for stream pointer*/
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecodeFrameLen(&ISACdec_obj->bitstr_obj, current_framesamples);
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
79fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  frame_mode = (int16_t)WEBRTC_SPL_DIV(*current_framesamples, MAX_FRAMESAMPLES); /* 0, or 1 */
80fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  processed_samples = (int16_t)WEBRTC_SPL_DIV(*current_framesamples, frame_mode+1); /* either 320 (20ms) or 480 (30, 60 ms) */
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecodeSendBandwidth(&ISACdec_obj->bitstr_obj, &BWno);
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* one loop if it's one frame (20 or 30ms), 2 loops if 2 frames bundled together (60ms) */
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* decode & dequantize pitch parameters */
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    err = WebRtcIsacfix_DecodePitchGain(&(ISACdec_obj->bitstr_obj), PitchGains_Q12);
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (err<0)  // error check
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return err;
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    err = WebRtcIsacfix_DecodePitchLag(&ISACdec_obj->bitstr_obj, PitchGains_Q12, PitchLags_Q7);
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (err<0)  // error check
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return err;
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
98fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    AvgPitchGain_Q12 = (int16_t)(((int32_t)PitchGains_Q12[0] + PitchGains_Q12[1] + PitchGains_Q12[2] + PitchGains_Q12[3])>>2);
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* decode & dequantize FiltCoef */
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    err = WebRtcIsacfix_DecodeLpc(gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15,
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  &ISACdec_obj->bitstr_obj, &model);
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (err<0)  // error check
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return err;
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* decode & dequantize spectrum */
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    len = WebRtcIsacfix_DecodeSpec(&ISACdec_obj->bitstr_obj, Vector_Word16_1, Vector_Word16_2, AvgPitchGain_Q12);
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (len < 0)  // error check
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return len;
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Why does this need Q16 in and out? /JS
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsacfix_Spec2Time(Vector_Word16_1, Vector_Word16_2, Vector_Word32_1, Vector_Word32_2);
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k=0; k<FRAMESAMPLES/2; k++) {
116fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      Vector_Word16_1[k] = (int16_t)WEBRTC_SPL_RSHIFT_W32(Vector_Word32_1[k]+64, 7); //Q16 -> Q9
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* ----  If this is recovery frame ---- */
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if( (ISACdec_obj->plcstr_obj).used == PLC_WAS_USED )
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (ISACdec_obj->plcstr_obj).used = PLC_NOT_USED;
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if( (ISACdec_obj->plcstr_obj).B < 1000 )
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      {
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 4000;
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACdec_obj->plcstr_obj.decayCoeffPriodic = WEBRTC_SPL_WORD16_MAX;    /* DECAY_RATE is in Q15 */
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACdec_obj->plcstr_obj.decayCoeffNoise = WEBRTC_SPL_WORD16_MAX;    /* DECAY_RATE is in Q15 */
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACdec_obj->plcstr_obj.pitchCycles = 0;
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
132fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      PitchGains_Q12[0] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(PitchGains_Q12[0], 700, 10 );
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* ---- Add-overlap ---- */
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcSpl_GetHanningWindow( overlapWin, RECOVERY_OVERLAP );
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for( k = 0; k < RECOVERY_OVERLAP; k++ )
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        Vector_Word16_1[k] = WEBRTC_SPL_ADD_SAT_W16(
138fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org            (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( (ISACdec_obj->plcstr_obj).overlapLP[k], overlapWin[RECOVERY_OVERLAP - k - 1], 14),
139fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org            (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( Vector_Word16_1[k], overlapWin[k], 14) );
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* --- Store side info --- */
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if( frame_nb == frame_mode )
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* --- LPC info */
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).lofilt_coefQ15, &lofilt_coefQ15[(SUBFRAMES-1)*ORDERLO], ORDERLO );
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).hifilt_coefQ15, &hifilt_coefQ15[(SUBFRAMES-1)*ORDERHI], ORDERHI );
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0] = gain_lo_hiQ17[(SUBFRAMES-1) * 2];
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1] = gain_lo_hiQ17[(SUBFRAMES-1) * 2 + 1];
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* --- LTP info */
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (ISACdec_obj->plcstr_obj).AvgPitchGain_Q12 = PitchGains_Q12[3];
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (ISACdec_obj->plcstr_obj).lastPitchGain_Q12 = PitchGains_Q12[3];
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = PitchLags_Q7[3];
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if( PitchLags_Q7[3] < 3000 )
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 += PitchLags_Q7[3];
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvIn, Vector_Word16_1, FRAMESAMPLES/2 );
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* inverse pitch filter */
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2, &ISACdec_obj->pitchfiltstr_obj, PitchLags_Q7, PitchGains_Q12, 4);
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if( frame_nb == frame_mode )
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvOut, &(Vector_Word16_2[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10)]), PITCH_MAX_LAG );
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* reduce gain to compensate for pitch enhancer */
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* gain = 1.0f - 0.45f * AvgPitchGain; */
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(AvgPitchGain_Q12, 29, 0); // Q18
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmp32b = 262144 - tmp32a;  // Q18
180fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    gainQ13 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5); // Q13
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < FRAMESAMPLES/2; k++)
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
184fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      Vector_Word32_1[k] = (int32_t) WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(Vector_Word16_2[k], gainQ13), 3); // Q25
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* perceptual post-filtering (using normalized lattice filter) */
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsacfix_NormLatticeFilterAr(ORDERLO, (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* --- Store Highpass Residual --- */
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < FRAMESAMPLES/2; k++)
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      Vector_Word32_1[k]    = WEBRTC_SPL_LSHIFT_W32(Vector_Word32_2[k], 9); // Q16 -> Q25
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for( k = 0; k < PITCH_MAX_LAG + 10; k++ )
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (ISACdec_obj->plcstr_obj).prevHP[k] = Vector_Word32_1[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10) + k];
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsacfix_NormLatticeFilterAr(ORDERHI, (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      Vector_Word32_1, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* recombine the 2 bands */
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Form the polyphase signals, and compensate for DC offset */
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k=0;k<FRAMESAMPLES/2;k++) {
207fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      tmp_1 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1)); /* Construct a new upper channel signal*/
208fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]-Vector_Word16_2[k])); /* Construct a new lower channel signal*/
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      Vector_Word16_1[k] = tmp_1;
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      Vector_Word16_2[k] = tmp_2;
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1, Vector_Word16_2, signal_out16 + frame_nb * processed_samples, &ISACdec_obj->postfiltbankstr_obj);
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return len;
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
218