niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 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_EnhancerInterface.c |
| 16 | |
| 17 | ******************************************************************/ |
| 18 | |
bjornv@webrtc.org | 5227534 | 2014-08-20 10:09:34 +0000 | [diff] [blame] | 19 | #include <string.h> |
| 20 | |
Mirko Bonadei | 06c2aa9 | 2018-02-01 15:11:41 +0100 | [diff] [blame^] | 21 | #include "modules/audio_coding/codecs/ilbc/defines.h" |
| 22 | #include "modules/audio_coding/codecs/ilbc/constants.h" |
| 23 | #include "modules/audio_coding/codecs/ilbc/xcorr_coef.h" |
| 24 | #include "modules/audio_coding/codecs/ilbc/enhancer.h" |
| 25 | #include "modules/audio_coding/codecs/ilbc/hp_output.h" |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 26 | |
| 27 | |
| 28 | |
| 29 | /*----------------------------------------------------------------* |
| 30 | * interface for enhancer |
| 31 | *---------------------------------------------------------------*/ |
| 32 | |
kwiberg | affcac4 | 2016-09-01 12:47:17 -0700 | [diff] [blame] | 33 | size_t // (o) Estimated lag in end of in[] |
| 34 | WebRtcIlbcfix_EnhancerInterface( |
| 35 | int16_t* out, // (o) enhanced signal |
| 36 | const int16_t* in, // (i) unenhanced signal |
| 37 | IlbcDecoder* iLBCdec_inst) { // (i) buffers etc |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 38 | size_t iblock; |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 39 | size_t lag=20, tlag=20; |
| 40 | size_t inLen=iLBCdec_inst->blockl+120; |
| 41 | int16_t scale, scale1; |
| 42 | size_t plc_blockl; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 43 | int16_t *enh_buf; |
| 44 | size_t *enh_period; |
| 45 | int32_t tmp1, tmp2, max; |
| 46 | size_t new_blocks; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 47 | int16_t *enh_bufPtr1; |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 48 | size_t i; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 49 | size_t k; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 50 | int16_t EnChange; |
| 51 | int16_t SqrtEnChange; |
| 52 | int16_t inc; |
| 53 | int16_t win; |
| 54 | int16_t *tmpW16ptr; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 55 | size_t startPos; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 56 | int16_t *plc_pred; |
kwiberg | affcac4 | 2016-09-01 12:47:17 -0700 | [diff] [blame] | 57 | const int16_t *target, *regressor; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 58 | int16_t max16; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 59 | int shifts; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 60 | int32_t ener; |
| 61 | int16_t enerSh; |
| 62 | int16_t corrSh; |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 63 | size_t ind; |
| 64 | int16_t sh; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 65 | size_t start, stop; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 66 | /* Stack based */ |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 67 | int16_t totsh[3]; |
| 68 | int16_t downsampled[(BLOCKL_MAX+120)>>1]; /* length 180 */ |
| 69 | int32_t corr32[50]; |
| 70 | int32_t corrmax[3]; |
| 71 | int16_t corr16[3]; |
| 72 | int16_t en16[3]; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 73 | size_t lagmax[3]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 74 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 75 | plc_pred = downsampled; /* Reuse memory since plc_pred[ENH_BLOCKL] and |
| 76 | downsampled are non overlapping */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 77 | enh_buf=iLBCdec_inst->enh_buf; |
| 78 | enh_period=iLBCdec_inst->enh_period; |
| 79 | |
| 80 | /* Copy in the new data into the enhancer buffer */ |
bjornv@webrtc.org | 5227534 | 2014-08-20 10:09:34 +0000 | [diff] [blame] | 81 | memmove(enh_buf, &enh_buf[iLBCdec_inst->blockl], |
| 82 | (ENH_BUFL - iLBCdec_inst->blockl) * sizeof(*enh_buf)); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 83 | |
| 84 | WEBRTC_SPL_MEMCPY_W16(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl], in, |
| 85 | iLBCdec_inst->blockl); |
| 86 | |
| 87 | /* Set variables that are dependent on frame size */ |
| 88 | if (iLBCdec_inst->mode==30) { |
| 89 | plc_blockl=ENH_BLOCKL; |
| 90 | new_blocks=3; |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 91 | startPos=320; /* Start position for enhancement |
| 92 | (640-new_blocks*ENH_BLOCKL-80) */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 93 | } else { |
| 94 | plc_blockl=40; |
| 95 | new_blocks=2; |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 96 | startPos=440; /* Start position for enhancement |
| 97 | (640-new_blocks*ENH_BLOCKL-40) */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | /* Update the pitch prediction for each enhancer block, move the old ones */ |
bjornv@webrtc.org | 5227534 | 2014-08-20 10:09:34 +0000 | [diff] [blame] | 101 | memmove(enh_period, &enh_period[new_blocks], |
| 102 | (ENH_NBLOCKS_TOT - new_blocks) * sizeof(*enh_period)); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 103 | |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 104 | WebRtcSpl_DownsampleFast( |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 105 | enh_buf+ENH_BUFL-inLen, /* Input samples */ |
Peter Kasting | b7e5054 | 2015-06-11 12:55:50 -0700 | [diff] [blame] | 106 | inLen + ENH_BUFL_FILTEROVERHEAD, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 107 | downsampled, |
Peter Kasting | b7e5054 | 2015-06-11 12:55:50 -0700 | [diff] [blame] | 108 | inLen / 2, |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 109 | (int16_t*)WebRtcIlbcfix_kLpFiltCoefs, /* Coefficients in Q12 */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 110 | FILTERORDER_DS_PLUS1, /* Length of filter (order-1) */ |
| 111 | FACTOR_DS, |
| 112 | DELAY_DS); |
| 113 | |
| 114 | /* Estimate the pitch in the down sampled domain. */ |
| 115 | for(iblock = 0; iblock<new_blocks; iblock++){ |
| 116 | |
| 117 | /* references */ |
Peter Kasting | f045e4d | 2015-06-10 21:15:38 -0700 | [diff] [blame] | 118 | target = downsampled + 60 + iblock * ENH_BLOCKL_HALF; |
| 119 | regressor = target - 10; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 120 | |
| 121 | /* scaling */ |
Peter Kasting | b7e5054 | 2015-06-11 12:55:50 -0700 | [diff] [blame] | 122 | max16 = WebRtcSpl_MaxAbsValueW16(®ressor[-50], ENH_BLOCKL_HALF + 50 - 1); |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 123 | shifts = WebRtcSpl_GetSizeInBits((uint32_t)(max16 * max16)) - 25; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 124 | shifts = WEBRTC_SPL_MAX(0, shifts); |
| 125 | |
| 126 | /* compute cross correlation */ |
Peter Kasting | a8b335c | 2015-06-11 18:51:20 -0700 | [diff] [blame] | 127 | WebRtcSpl_CrossCorrelation(corr32, target, regressor, ENH_BLOCKL_HALF, 50, |
| 128 | shifts, -1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 129 | |
| 130 | /* Find 3 highest correlations that should be compared for the |
| 131 | highest (corr*corr)/ener */ |
| 132 | |
| 133 | for (i=0;i<2;i++) { |
| 134 | lagmax[i] = WebRtcSpl_MaxIndexW32(corr32, 50); |
| 135 | corrmax[i] = corr32[lagmax[i]]; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 136 | start = WEBRTC_SPL_MAX(2, lagmax[i]) - 2; |
| 137 | stop = WEBRTC_SPL_MIN(47, lagmax[i]) + 2; |
| 138 | for (k = start; k <= stop; k++) { |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 139 | corr32[k] = 0; |
| 140 | } |
| 141 | } |
| 142 | lagmax[2] = WebRtcSpl_MaxIndexW32(corr32, 50); |
| 143 | corrmax[2] = corr32[lagmax[2]]; |
| 144 | |
| 145 | /* Calculate normalized corr^2 and ener */ |
| 146 | for (i=0;i<3;i++) { |
| 147 | corrSh = 15-WebRtcSpl_GetSizeInBits(corrmax[i]); |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 148 | ener = WebRtcSpl_DotProductWithScale(regressor - lagmax[i], |
| 149 | regressor - lagmax[i], |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 150 | ENH_BLOCKL_HALF, shifts); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 151 | enerSh = 15-WebRtcSpl_GetSizeInBits(ener); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 152 | corr16[i] = (int16_t)WEBRTC_SPL_SHIFT_W32(corrmax[i], corrSh); |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 153 | corr16[i] = (int16_t)((corr16[i] * corr16[i]) >> 16); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 154 | en16[i] = (int16_t)WEBRTC_SPL_SHIFT_W32(ener, enerSh); |
kwiberg | 4f6c2b6 | 2016-05-26 03:40:51 -0700 | [diff] [blame] | 155 | totsh[i] = enerSh - 2 * corrSh; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | /* Compare lagmax[0..3] for the (corr^2)/ener criteria */ |
| 159 | ind = 0; |
| 160 | for (i=1; i<3; i++) { |
| 161 | if (totsh[ind] > totsh[i]) { |
| 162 | sh = WEBRTC_SPL_MIN(31, totsh[ind]-totsh[i]); |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 163 | if (corr16[ind] * en16[i] < (corr16[i] * en16[ind]) >> sh) { |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 164 | ind = i; |
| 165 | } |
| 166 | } else { |
| 167 | sh = WEBRTC_SPL_MIN(31, totsh[i]-totsh[ind]); |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 168 | if ((corr16[ind] * en16[i]) >> sh < corr16[i] * en16[ind]) { |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 169 | ind = i; |
| 170 | } |
| 171 | } |
| 172 | } |
| 173 | |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 174 | lag = lagmax[ind] + 10; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 175 | |
| 176 | /* Store the estimated lag in the non-downsampled domain */ |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 177 | enh_period[ENH_NBLOCKS_TOT - new_blocks + iblock] = lag * 8; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 178 | |
| 179 | /* Store the estimated lag for backward PLC */ |
| 180 | if (iLBCdec_inst->prev_enh_pl==1) { |
| 181 | if (!iblock) { |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 182 | tlag = lag * 2; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 183 | } |
| 184 | } else { |
| 185 | if (iblock==1) { |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 186 | tlag = lag * 2; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 187 | } |
| 188 | } |
| 189 | |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 190 | lag *= 2; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 191 | } |
| 192 | |
| 193 | if ((iLBCdec_inst->prev_enh_pl==1)||(iLBCdec_inst->prev_enh_pl==2)) { |
| 194 | |
| 195 | /* Calculate the best lag of the new frame |
| 196 | This is used to interpolate backwards and mix with the PLC'd data |
| 197 | */ |
| 198 | |
| 199 | /* references */ |
| 200 | target=in; |
| 201 | regressor=in+tlag-1; |
| 202 | |
| 203 | /* scaling */ |
Peter Kasting | b7e5054 | 2015-06-11 12:55:50 -0700 | [diff] [blame] | 204 | max16 = WebRtcSpl_MaxAbsValueW16(regressor, plc_blockl + 3 - 1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 205 | if (max16>5000) |
| 206 | shifts=2; |
| 207 | else |
| 208 | shifts=0; |
| 209 | |
| 210 | /* compute cross correlation */ |
Peter Kasting | a8b335c | 2015-06-11 18:51:20 -0700 | [diff] [blame] | 211 | WebRtcSpl_CrossCorrelation(corr32, target, regressor, plc_blockl, 3, shifts, |
| 212 | 1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 213 | |
| 214 | /* find lag */ |
| 215 | lag=WebRtcSpl_MaxIndexW32(corr32, 3); |
| 216 | lag+=tlag-1; |
| 217 | |
| 218 | /* Copy the backward PLC to plc_pred */ |
| 219 | |
| 220 | if (iLBCdec_inst->prev_enh_pl==1) { |
| 221 | if (lag>plc_blockl) { |
| 222 | WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-plc_blockl], plc_blockl); |
| 223 | } else { |
| 224 | WEBRTC_SPL_MEMCPY_W16(&plc_pred[plc_blockl-lag], in, lag); |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 225 | WEBRTC_SPL_MEMCPY_W16( |
| 226 | plc_pred, &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl+lag], |
| 227 | (plc_blockl-lag)); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 228 | } |
| 229 | } else { |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 230 | size_t pos; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 231 | |
| 232 | pos = plc_blockl; |
| 233 | |
| 234 | while (lag<pos) { |
| 235 | WEBRTC_SPL_MEMCPY_W16(&plc_pred[pos-lag], in, lag); |
| 236 | pos = pos - lag; |
| 237 | } |
| 238 | WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-pos], pos); |
| 239 | |
| 240 | } |
| 241 | |
| 242 | if (iLBCdec_inst->prev_enh_pl==1) { |
| 243 | /* limit energy change |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 244 | if energy in backward PLC is more than 4 times higher than the forward |
| 245 | PLC, then reduce the energy in the backward PLC vector: |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 246 | sample 1...len-16 set energy of the to 4 times forward PLC |
| 247 | sample len-15..len interpolate between 4 times fw PLC and bw PLC energy |
| 248 | |
| 249 | Note: Compared to floating point code there is a slight change, |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 250 | the window is 16 samples long instead of 10 samples to simplify the |
| 251 | calculations |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 252 | */ |
| 253 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 254 | max=WebRtcSpl_MaxAbsValueW16( |
| 255 | &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], plc_blockl); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 256 | max16=WebRtcSpl_MaxAbsValueW16(plc_pred, plc_blockl); |
| 257 | max = WEBRTC_SPL_MAX(max, max16); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 258 | scale=22-(int16_t)WebRtcSpl_NormW32(max); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 259 | scale=WEBRTC_SPL_MAX(scale,0); |
| 260 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 261 | tmp2 = WebRtcSpl_DotProductWithScale( |
| 262 | &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], |
| 263 | &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], |
| 264 | plc_blockl, scale); |
| 265 | tmp1 = WebRtcSpl_DotProductWithScale(plc_pred, plc_pred, |
| 266 | plc_blockl, scale); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 267 | |
| 268 | /* Check the energy difference */ |
| 269 | if ((tmp1>0)&&((tmp1>>2)>tmp2)) { |
| 270 | /* EnChange is now guaranteed to be <0.5 |
| 271 | Calculate EnChange=tmp2/tmp1 in Q16 |
| 272 | */ |
| 273 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 274 | scale1=(int16_t)WebRtcSpl_NormW32(tmp1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 275 | tmp1=WEBRTC_SPL_SHIFT_W32(tmp1, (scale1-16)); /* using 15 bits */ |
| 276 | |
| 277 | tmp2=WEBRTC_SPL_SHIFT_W32(tmp2, (scale1)); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 278 | EnChange = (int16_t)WebRtcSpl_DivW32W16(tmp2, |
| 279 | (int16_t)tmp1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 280 | |
| 281 | /* Calculate the Sqrt of the energy in Q15 ((14+16)/2) */ |
bjornv@webrtc.org | 4ab23d0 | 2015-03-20 06:01:06 +0000 | [diff] [blame] | 282 | SqrtEnChange = (int16_t)WebRtcSpl_SqrtFloor(EnChange << 14); |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 283 | |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 284 | |
| 285 | /* Multiply first part of vector with 2*SqrtEnChange */ |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 286 | WebRtcSpl_ScaleVector(plc_pred, plc_pred, SqrtEnChange, plc_blockl-16, |
| 287 | 14); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 288 | |
| 289 | /* Calculate increase parameter for window part (16 last samples) */ |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 290 | /* (1-2*SqrtEnChange)/16 in Q15 */ |
bjornv@webrtc.org | f71785c | 2014-10-08 15:36:30 +0000 | [diff] [blame] | 291 | inc = 2048 - (SqrtEnChange >> 3); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 292 | |
| 293 | win=0; |
| 294 | tmpW16ptr=&plc_pred[plc_blockl-16]; |
| 295 | |
| 296 | for (i=16;i>0;i--) { |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 297 | *tmpW16ptr = (int16_t)( |
| 298 | (*tmpW16ptr * (SqrtEnChange + (win >> 1))) >> 14); |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 299 | /* multiply by (2.0*SqrtEnChange+win) */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 300 | |
| 301 | win += inc; |
| 302 | tmpW16ptr++; |
| 303 | } |
| 304 | } |
| 305 | |
| 306 | /* Make the linear interpolation between the forward PLC'd data |
| 307 | and the backward PLC'd data (from the new frame) |
| 308 | */ |
| 309 | |
| 310 | if (plc_blockl==40) { |
| 311 | inc=400; /* 1/41 in Q14 */ |
| 312 | } else { /* plc_blockl==80 */ |
| 313 | inc=202; /* 1/81 in Q14 */ |
| 314 | } |
| 315 | win=0; |
| 316 | enh_bufPtr1=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl]; |
| 317 | for (i=0; i<plc_blockl; i++) { |
| 318 | win+=inc; |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 319 | *enh_bufPtr1 = (int16_t)((*enh_bufPtr1 * win) >> 14); |
| 320 | *enh_bufPtr1 += (int16_t)( |
| 321 | ((16384 - win) * plc_pred[plc_blockl - 1 - i]) >> 14); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 322 | enh_bufPtr1--; |
| 323 | } |
| 324 | } else { |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 325 | int16_t *synt = &downsampled[LPC_FILTERORDER]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 326 | |
| 327 | enh_bufPtr1=&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl]; |
| 328 | WEBRTC_SPL_MEMCPY_W16(enh_bufPtr1, plc_pred, plc_blockl); |
| 329 | |
| 330 | /* Clear fileter memory */ |
| 331 | WebRtcSpl_MemSetW16(iLBCdec_inst->syntMem, 0, LPC_FILTERORDER); |
| 332 | WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemy, 0, 4); |
| 333 | WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemx, 0, 2); |
| 334 | |
| 335 | /* Initialize filter memory by filtering through 2 lags */ |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 336 | WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], iLBCdec_inst->syntMem, |
| 337 | LPC_FILTERORDER); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 338 | WebRtcSpl_FilterARFastQ12( |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 339 | enh_bufPtr1, |
| 340 | synt, |
| 341 | &iLBCdec_inst->old_syntdenum[ |
Peter Kasting | 728d903 | 2015-06-11 14:31:38 -0700 | [diff] [blame] | 342 | (iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)], |
| 343 | LPC_FILTERORDER+1, lag); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 344 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 345 | WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], &synt[lag-LPC_FILTERORDER], |
| 346 | LPC_FILTERORDER); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 347 | WebRtcIlbcfix_HpOutput(synt, (int16_t*)WebRtcIlbcfix_kHpOutCoefs, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 348 | iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx, |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 349 | lag); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 350 | WebRtcSpl_FilterARFastQ12( |
| 351 | enh_bufPtr1, synt, |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 352 | &iLBCdec_inst->old_syntdenum[ |
Peter Kasting | 728d903 | 2015-06-11 14:31:38 -0700 | [diff] [blame] | 353 | (iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)], |
| 354 | LPC_FILTERORDER+1, lag); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 355 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 356 | WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &synt[lag-LPC_FILTERORDER], |
| 357 | LPC_FILTERORDER); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 358 | WebRtcIlbcfix_HpOutput(synt, (int16_t*)WebRtcIlbcfix_kHpOutCoefs, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 359 | iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx, |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 360 | lag); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 361 | } |
| 362 | } |
| 363 | |
| 364 | |
| 365 | /* Perform enhancement block by block */ |
| 366 | |
| 367 | for (iblock = 0; iblock<new_blocks; iblock++) { |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 368 | WebRtcIlbcfix_Enhancer(out + iblock * ENH_BLOCKL, |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 369 | enh_buf, |
| 370 | ENH_BUFL, |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 371 | iblock * ENH_BLOCKL + startPos, |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 372 | enh_period, |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 373 | WebRtcIlbcfix_kEnhPlocs, ENH_NBLOCKS_TOT); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 374 | } |
| 375 | |
| 376 | return (lag); |
| 377 | } |